From c1c64c1591fa7757d5d15fe58198832a98d5d7b6 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sun, 13 Nov 2011 00:38:59 +0100 Subject: [PATCH] mars_nwe-0.99.pl19 --- connect.c | 1757 +++++++++++++---------- connect.h | 133 +- dbmtool.c | 13 +- debmask.h | 2 + doc/BUGS.nl | 43 + doc/CHANGES | 139 +- doc/CREDITS | 48 +- doc/FAQS | 6 +- doc/FILESHARING | 85 ++ doc/HOWTO.ger | 4 +- doc/INSTALL | 2 +- doc/INSTALL.nl | 133 ++ doc/NEWS | 13 + doc/PIPE-FS | 15 +- doc/PIPE-FS.ger | 99 +- doc/README | 2 +- doc/README.FREEBSD | 74 + doc/README.ger | 2 +- doc/TRUSTEES | 72 + doc/VRAGEN.NL | 30 + doc/mars_nwe.lsm | 16 +- emutli.c | 112 +- emutli.h | 24 +- emutli1.c | 119 +- emutli1.h | 7 +- examples/comm.c | 202 ++- examples/comm.exe | Bin 35048 -> 36062 bytes examples/comm32.exe | Bin 0 -> 35328 bytes examples/config.h | 8 +- examples/e.pck | Bin 0 -> 447 bytes examples/mk | 1 + examples/mk.li | 41 +- examples/nw.ini | 165 ++- examples/nwopt | 5 +- examples/unxcomm.c | 65 +- extpipe.c | 34 +- extpipe.h | 4 +- ftrustee.c | 233 +++ ipxif.c | 197 +++ makefile.unx | 58 +- namspace.c | 1273 ++++++++++++----- ncpserv.c | 4 + net.h | 30 +- net1.c | 43 +- net1.h | 7 +- nwattrib.c | 340 ++--- nwattrib.h | 25 +- nwbind.c | 615 ++++++-- nwbind.h | 25 +- nwconn.c | 3324 ++++++++++++++++++++++++------------------- nwconn.h | 3 +- nwdbm.c | 1543 ++++++++++++++------ nwdbm.h | 77 +- nwfile.c | 1115 ++++++++++----- nwfile.h | 20 +- nwqconn.c | 113 +- nwqconn.h | 10 +- nwqueue.c | 249 +++- nwqueue.h | 11 +- nwroute.c | 45 +- nwroute1.c | 22 +- nwserv.c | 174 +-- nwserv.h | 4 +- nwshare.c | 757 ++++++++-- nwshare.h | 15 +- nwvolume.c | 365 ++++- nwvolume.h | 66 +- tools.c | 196 ++- tools.h | 23 +- tools.sh | 33 + trustee.c | 923 ++++++++++++ trustee.h | 61 + unxfile.c | 17 +- unxfile.h | 15 +- unxlog.c | 4 +- 75 files changed, 11044 insertions(+), 4466 deletions(-) create mode 100644 doc/BUGS.nl create mode 100644 doc/FILESHARING create mode 100644 doc/INSTALL.nl create mode 100644 doc/README.FREEBSD create mode 100644 doc/TRUSTEES create mode 100644 doc/VRAGEN.NL create mode 100644 examples/comm32.exe create mode 100644 examples/e.pck create mode 100755 examples/mk create mode 100644 ftrustee.c create mode 100644 ipxif.c create mode 100755 tools.sh create mode 100644 trustee.c create mode 100644 trustee.h diff --git a/connect.c b/connect.c index 25c4500..6c65645 100644 --- a/connect.c +++ b/connect.c @@ -1,5 +1,5 @@ -/* connect.c 01-Feb-98 */ -/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany +/* connect.c 15-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 @@ -31,21 +31,24 @@ int server_version_flags=0; int max_burst_send_size=0x2000; int max_burst_recv_size=0x2000; +int default_uid=-1; +int default_gid=-1; + #ifdef TEST_FNAME static int test_handle=-1; #endif -static int default_uid=-1; -static int default_gid=-1; -static int default_umode_dir=0775; -static int default_umode_file=0664; +static int default_umode_dir = 0751; +static int default_umode_file = 0640; static int act_umode_dir=0; static int act_umode_file=0; #include "nwfname.h" #include "nwvolume.h" +#include "nwshare.h" #include "nwattrib.h" +#include "trustee.h" #include "nwfile.h" #include "nwconn.h" #include "namspace.h" @@ -69,7 +72,9 @@ int used_dirs=0; int act_uid=-1; /* unix uid 0=root */ int act_gid=-1; /* unix gid */ int act_obj_id=0L; /* mars_nwe UID, 0=not logged in, 1=supervisor */ +int act_id_flags=0; /* &1 == supervisor equivalence !!! */ int entry8_flags=0; /* special flags, see examples nw.ini, entry 8 */ +int entry31_flags=0; /* not used yet */ static gid_t *act_grouplist=NULL; /* first element is counter !! */ @@ -87,9 +92,9 @@ typedef struct { char *kpath; /* one char after unixname */ int vol_options; /* searchoptions */ int volume; /* Volume Number */ - int sequence; /* Search sequence */ off_t dirpos; /* Current pos in unix dir */ + int no_search_trustee; /* mst:15-Apr-00 */ } DIR_HANDLE; static DIR_HANDLE dir_handles[MAX_DIRHANDLES]; @@ -105,20 +110,22 @@ static char *build_unix_name(NW_PATH *nwpath, int modus) { static char unixname[300]; /* must be big enouugh */ int volume = nwpath->volume; - char *p, *pp; + char *p; if (volume < 0 || volume >= used_nw_volumes - || !nw_volumes[volume].unixnamlen) { - errorp(0, "build_unix_name", "volume=%d not ok\n", volume); - strcpy(unixname, "Z/Z/Z/Z"); /* */ + || !nw_volumes[volume].unixnamlen + || nw_volumes[volume].unixnamlen > 250) { + errorp(10, "build_unix_name", "volume=%d not ok\n", volume); + xstrcpy(unixname, "Z/Z/Z/Z"); /* */ return(unixname); } - strcpy(unixname, (char*)nw_volumes[volume].unixname); /* first UNIXNAME VOLUME */ + memcpy(unixname, (char*)nw_volumes[volume].unixname, + nw_volumes[volume].unixnamlen ); /* first UNIXNAME VOLUME */ + + p = unixname + nw_volumes[volume].unixnamlen; + p += strmaxcpy(p, (char*)nwpath->path, sizeof(unixname) - nw_volumes[volume].unixnamlen -1); /* now the path */ - p = pp = unixname+strlen(unixname); - strcpy(p, (char*)nwpath->path); /* now the path */ - p += strlen((char*)nwpath->path); if ( (!(modus & 1)) && nwpath->fn[0]) - strcpy(p, (char*)nwpath->fn); /* and now fn */ + strmaxcpy(p, (char*)nwpath->fn, sizeof(unixname) - (int)(p-unixname) -1); /* and now fn */ else if ((modus & 2) && (*(p-1) == '/')) { if (p > unixname+1) *(--p) = '\0'; else { @@ -131,7 +138,7 @@ static char *build_unix_name(NW_PATH *nwpath, int modus) } -static int new_dir_handle(int dev, ino_t inode, NW_PATH *nwpath) +static int new_dir_handle(struct stat *stb, NW_PATH *nwpath) /* * RETURN=errorcode (<0) or dir_handle */ @@ -151,7 +158,7 @@ static int new_dir_handle(int dev, ino_t inode, NW_PATH *nwpath) if (!dh->inode) { if (!nhandle) nhandle = rethandle+1; - } else if (dh->dev == dev && dh->inode == inode + } else if (dh->dev == stb->st_dev && dh->inode == stb->st_ino && dh->volume == nwpath->volume){ nhandle = rethandle+1; break; @@ -175,15 +182,26 @@ static int new_dir_handle(int dev, ino_t inode, NW_PATH *nwpath) /* init dir_handle */ dh=&(dir_handles[rethandle-1]); - strcpy(dh->unixname, build_unix_name(nwpath, 0)); - dh->kpath = dh->unixname + strlen(dh->unixname); - if (dh->f) + dh->kpath = dh->unixname + xstrcpy(dh->unixname, build_unix_name(nwpath, 0)); + if (dh->f) { closedir(dh->f); - if ((dh->f = opendir(dh->unixname)) != (DIR*) NULL){ + dh->f=NULL; + } + + if ( ( !(dh->no_search_trustee=tru_eff_rights_exists(nwpath->volume, dh->unixname, stb, TRUSTEE_F))) + || (dh->no_search_trustee & TRUSTEE_T) ) { + if ((dh->f=opendir(dh->unixname)) == (DIR*)NULL) { + seteuid(0); + dh->f=opendir(dh->unixname); + reseteuid(); + } + } + + if (NULL != dh->f) { dh->volume = nwpath->volume; dh->vol_options = nw_volumes[dh->volume].options; - dh->dev = dev; - dh->inode = inode; + dh->dev = stb->st_dev; + dh->inode = stb->st_ino; dh->timestamp = akttime; dh->sequence = 0; dh->dirpos = (off_t)0; @@ -226,8 +244,8 @@ void set_default_guid(void) "Cannot set default gid=%d and uid=%d" , default_gid, default_uid); exit(1); } - act_gid = default_gid; - act_uid = default_uid; + act_gid = default_gid; + act_uid = default_uid; act_umode_dir = default_umode_dir; act_umode_file = default_umode_file; xfree(act_grouplist); @@ -299,27 +317,14 @@ int in_act_groups(gid_t gid) return(0); } -void set_nw_user(int gid, int uid, - uint32 obj_id, uint8 *objname, - int homepathlen, uint8 *homepath) -{ - nwconn_set_program_title(objname); - set_guid(gid, uid); - act_obj_id=obj_id; - XDPRINTF((5, 0, "actual obj_id is set to 0x%x", obj_id)); - nw_setup_vol_opts(act_gid, act_uid, - act_umode_dir, act_umode_file, - homepathlen, homepath); - nw_setup_home_vol(homepathlen, homepath); -} - -int get_real_access(struct stat *stb) +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) ; + if (!act_uid) + return(0x10 | R_OK | W_OK | X_OK) ; /* root */ else { if (act_uid == stb->st_uid) { mode |= 0x10; @@ -350,6 +355,32 @@ int get_real_access(struct stat *stb) return(mode); } + + +/* next routine is called after new login */ +void set_nw_user(int gid, int uid, + int id_flags, + uint32 obj_id, uint8 *objname, + int unxloginlen, uint8 *unxloginname, + int grpcount, uint32 *grps) +{ + uint8 unxlogin[20]; + strmaxcpy(unxlogin, unxloginname, min(unxloginlen, sizeof(unxlogin)-1)); + nwconn_set_program_title(objname); + set_guid(gid, uid); + act_obj_id = obj_id; + act_id_flags = id_flags; + XDPRINTF((5, 0, "actual obj_id is set to 0x%x", obj_id)); + if ((act_id_flags&1) && obj_id != 1) { + XDPRINTF((1, 0, "logged in user %s (%s) has supervisor privilegs", objname, unxlogin)); + } + nw_setup_vol_opts(act_gid, act_uid, + act_umode_dir, act_umode_file, + unxlogin); + tru_init_trustees(grpcount, grps); +} + + uint32 get_file_owner(struct stat *stb) /* returns nwuser creator of file */ { @@ -366,118 +397,70 @@ static char *conn_get_nwpath_name(NW_PATH *p) static char nwpathname[300]; char volname[100]; if (p->volume < 0 || p->volume >= used_nw_volumes) { - sprintf(volname, "<%d=NOT-OK>", (int)p->volume); - } else strcpy(volname, (char*)nw_volumes[p->volume].sysname); - sprintf(nwpathname, "%s:%s%s", volname, p->path, p->fn); + slprintf(volname, sizeof(volname)-1, "<%d=NOT-OK>", (int)p->volume); + } else xstrcpy(volname, (char*)nw_volumes[p->volume].sysname); + slprintf(nwpathname, sizeof(nwpathname)-1, "%s:%s%s", volname, p->path, p->fn); return(nwpathname); } +/* new from Andrew Sapozhnikov + * added in 0.99.pl7, removes old x_str_match routine + * Do not work for namespace routines, see namespace.c !! + */ +/* NW3.12/MSDOS-like filename matching. * + * Wildcards '*' and '?' allowed. */ static int x_str_match(uint8 *s, uint8 *p, int soptions) { - uint8 pc, sc; - uint state = 0; - uint8 anf, ende; - int not = 0; - uint found = 0; - while ( (pc = *p++) != 0) { + while (*p) { + switch (*p) { + case 0xbf: + case '?': if (*s && *s != '.') s++; + p++; + break; +#if 0 + case 0xaa: + case '*': while (*s && *s != '.') s++; + while (*p && *p != '.' && *p != 0xae) p++; + break; +#else + /* changed 27-May-98, 0.99.pl10 to handle '*' correct, + * and to handle '*xy.xyz' in a `better` (non DOS) way. + * now I know again why my old routine was so terrible ;-) + */ - if (state != 100) { - if (pc == 255 && (*p == '*' || *p == '?' - || *p==0xaa || *p==0xae || *p==0xbf || *p=='.')) { - pc=*p++; - } + case 0xaa: + case '*': ++p; + if (*p) { + while (*s && *s != '.') { + if (x_str_match(s, p, soptions)) + return(1); + else + s++; + } + } else { + if (*(p-1) == '*') /* last star '*' match everything */ + return(1); + else /* but 0xaa not */ + while (*s && *s != '.') s++; + } + break; +#endif + + case 0xae: + case '.': if (*s) { + if(*s != '.') return 0; + else s++; + } + p++; + break; + default : if (! ((soptions & VOL_OPTION_IGNCASE) ? + dfn_imatch(*s, *p) : (*s == *p)) ) return 0; + p++; + s++; - switch (pc) { - case 0xaa: pc='*'; break; - case 0xae: pc='.'; break; - case 0xbf: pc='?'; break; - } } - - switch (state){ - case 0 : - switch (pc) { - case '\\': /* any following char */ - if (*p++ != *s++) return(0); - break; - - case '?' : if (!*s || (sc = *s++) == '.') - state = 10; - break; - - case '.' : if (*s && pc != *s++) return(0); - break; - - case '*' : if (!*p) return(1); /* last star */ - while (*s) { - if (x_str_match(s, p, soptions) == 1) return(1); - else if (*s == '.') return(0); - ++s; - } - state = 30; - break; - - case '[' : if ( (*p == '!') || (*p == '^') ){ - ++p; - not = 1; - } - state = 100; - continue; - - default : /* 'normal' chars */ - if (soptions & VOL_OPTION_IGNCASE) { - if (!dfn_imatch(*s, pc)) - return(0); - } else if (pc != *s) return(0); - s++; - break; - - } /* switch */ - break; - - case 10 : if (pc != '*' && pc != '?' ) { - if (pc == '.') - state = 0; - else return(0); - } - break; - - case 30: if (pc != '.') return(0); - state = 31; - break; - - case 31: if (pc != '*' ) return(0); - break; - - case 100 : /* Bereich von Zeichen */ - sc = *s++; - found = not; - if (!sc) return(0); - do { - if (pc == '\\') pc = *(p++); - if (!pc) return(0); - anf = pc; - if (*p == '-' && *(p+1) != ']'){ - ende = *(++p); - p++; - } - else ende = anf; - if (found == not) { /* only if not found */ - if (anf == sc || (anf <= sc && sc <= ende)) - found = !not; - } - } while ((pc = *(p++)) != ']'); - if (! found ) return(0); - not = 0; - found = 0; - state = 0; - break; - - default : break; - } /* switch */ - } /* while */ - if (*s=='.' && *(s+1)=='\0') return(1); /* I hope this is right */ - return ( (*s) ? 0 : 1); + } + return (*s ? 0 : 1); } int fn_dos_match(uint8 *s, uint8 *p, int options) @@ -485,6 +468,16 @@ int fn_dos_match(uint8 *s, uint8 *p, int options) uint8 *ss=s; int len=0; int pf=0; + uint8 p_buff[200]; + uint8 *pp=p_buff; + + for (; *p; p++){ + if (*p != 0xff) + *pp++=*p; + } + *pp='\0'; + p=p_buff; + for (; *ss; ss++){ if (*ss == '.') { if (pf++) return(0); /* no 2. point */ @@ -506,63 +499,6 @@ int fn_dos_match(uint8 *s, uint8 *p, int options) return(x_str_match(s, p, options)); } -/* "Resolve" string 'topath' (possible with wildcards '?') using - * 'frompath' as source for substitution. Make changes directly in - * 'topath'. Return new length of topath (equal or less than original value) - * Routine from: Andrew Sapozhnikov - */ - -int apply_wildcards (uint8 *frompath, int flen, uint8 *topath, int tlen) -{ - int i,tlen2; - uint8 c,*topath2; - - for (i=flen; i > 0; i--) { - c=frompath[i-1]; - if (c == ':' || c == '\\' || c == '/') break; - } - frompath+=i; - flen-=i; - - for (i=tlen; i > 0; i--) { - c=topath[i-1]; - if(c == ':' || c == '\\' || c == '/') break; - } - topath2=(topath+=i); - tlen2=tlen-i; - - while (tlen2--) { - switch (c=*topath2++) { - case '?': - case 0xbf: - if (flen && *frompath != '.' && *frompath != 0xae) { - *topath++ = *frompath++; - flen--; - } else tlen--; - break; - case '.': - case 0xae: - while (flen && *frompath != '.' && *frompath != 0xae) { - frompath++; - flen--; - } - if (flen) { - frompath++; - flen--; - } - *topath++=c; - break; - default: - if (flen && *frompath != '.' && *frompath != 0xae) { - frompath++; - flen--; - } - *topath++=c; - } - } - return tlen; -} - typedef struct { int attrib; struct stat statb; @@ -575,7 +511,7 @@ static int func_search_entry(NW_PATH *nwpath, int attrib, /* returns > 0 if OK < 1 if not ok or not found */ { struct dirent* dirbuff; - DIR *f; + DIR *f=NULL; int result=0; int okflag=0; char xkpath[256]; @@ -590,14 +526,24 @@ static int func_search_entry(NW_PATH *nwpath, int attrib, fs->attrib = attrib; if (volume < 0 || volume >= used_nw_volumes) return(-1); /* something wrong */ else soptions = nw_volumes[volume].options; - strcpy((char*)entry, (char*)nwpath->fn); + xstrcpy(entry, (char*)nwpath->fn); nwpath->fn[0] = '\0'; - strcpy(xkpath, build_unix_name(nwpath, 1|2)); + xstrcpy(xkpath, build_unix_name(nwpath, 1|2)); XDPRINTF((5,0,"func_search_entry attrib=0x%x path:%s:, xkpath:%s:, entry:%s:", attrib, nwpath->path, xkpath, entry)); - if ((f=opendir(xkpath)) != (DIR*)NULL) { + + if ( (!stat(xkpath, &(fs->statb))) + && !tru_eff_rights_exists(volume, xkpath, &(fs->statb), TRUSTEE_F)) { + if ((f=opendir(xkpath)) == (DIR*)NULL) { + seteuid(0); + f=opendir(xkpath); + reseteuid(); + } + } + + if (f != (DIR*)NULL) { char *kpath=xkpath+strlen(xkpath); *kpath++ = '/'; while ((dirbuff = readdir(f)) != (struct dirent*)NULL){ @@ -608,17 +554,16 @@ static int func_search_entry(NW_PATH *nwpath, int attrib, xstrcpy(dname, name); unix2doscharset(dname); okflag = (name[0] != '.' && - ( (entry[0] == '*' && entry[1] == '\0') - || (!strcmp((char*)dname, (char*)entry)) + ( (!strcmp((char*)dname, (char*)entry)) || fn_dos_match(dname, entry, soptions))); if (okflag) { *kpath = '\0'; - strcpy(kpath, (char*)name); + strmaxcpy(kpath, (char*)name, sizeof(xkpath) - (int)(kpath-xkpath) -1 ); if (!s_stat(xkpath, &(fs->statb), NULL)) { okflag = ( ( ( (fs->statb.st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) || ( ( (fs->statb.st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10))); if (okflag){ - strcpy((char*)nwpath->fn, (char*)dname); + xstrcpy(nwpath->fn, (char*)dname); XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, fs->statb.st_mode)); result = (*fs_func)(nwpath, fs); if (result < 0) break; @@ -639,25 +584,37 @@ static int get_dir_entry(NW_PATH *nwpath, int attrib, struct stat *statb) -/* returns 1 if OK and 0 if not OK */ +/* returns 0 if OK and errcode if not OK */ { struct dirent* dirbuff; - DIR *f; - int okflag=0; + DIR *f=NULL; + int okflag=-0xff; /* not found */ char xkpath[256]; uint8 entry[256]; int volume = nwpath->volume; int soptions; int akt_sequence=0; - if (volume < 0 || volume >= used_nw_volumes) return(0); /* something wrong */ + int no_search_trustee = 0; + + if (volume < 0 || volume >= used_nw_volumes) return(-0x98); /* something wrong */ else soptions = nw_volumes[volume].options; - strcpy((char*)entry, (char*)nwpath->fn); + xstrcpy(entry, (char*)nwpath->fn); nwpath->fn[0] = '\0'; - strcpy(xkpath, build_unix_name(nwpath, 1|2)); + xstrcpy(xkpath, build_unix_name(nwpath, 1|2)); XDPRINTF((5,0,"get_dir_entry attrib=0x%x path:%s:, xkpath:%s:, entry:%s:", attrib, nwpath->path, xkpath, entry)); - if ((f=opendir(xkpath)) != (DIR*)NULL) { + if ( (!stat(xkpath, statb)) + && ( (!(no_search_trustee = tru_eff_rights_exists(volume, xkpath, statb, TRUSTEE_F))) + || (no_search_trustee&TRUSTEE_T)) ) { + if ((f=opendir(xkpath)) == (DIR*)NULL) { + seteuid(0); + f=opendir(xkpath); + reseteuid(); + } + } + + if (f != (DIR*)NULL) { char *kpath=xkpath+strlen(xkpath); *kpath++ = '/'; if (*sequence == MAX_U16) *sequence = 0; @@ -665,40 +622,48 @@ static int get_dir_entry(NW_PATH *nwpath, while (akt_sequence++ < *sequence) { if (NULL == readdir(f)) { closedir(f); - return(0); + return(-0xff); } } while ((dirbuff = readdir(f)) != (struct dirent*)NULL){ - okflag = 0; + okflag = -0xff; (*sequence)++; if (dirbuff->d_ino) { uint8 *name=(uint8*)(dirbuff->d_name); uint8 dname[256]; xstrcpy(dname, name); unix2doscharset(dname); - okflag = (name[0] != '.' && - ( (entry[0] == '*' && entry[1] == '\0') - || (!strcmp((char*)dname, (char*)entry)) - || fn_dos_match(dname, entry, soptions))); - if (okflag) { + okflag = ((name[0] != '.' && + ( (!strcmp((char*)dname, (char*)entry)) + || fn_dos_match(dname, entry, soptions)))) ? 0 : -0xff; + if (!okflag) { *kpath = '\0'; - strcpy(kpath, (char*)name); + strmaxcpy(kpath, (char*)name, sizeof(xkpath) - (int)(kpath-xkpath) -1); if (!s_stat(xkpath, statb, NULL)) { - okflag = ( ( ( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) - || ( ( (statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10))); - if (okflag){ - strcpy((char*)nwpath->fn, (char*)dname); - XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, statb->st_mode)); - break; /* ready */ + okflag = (( ( ( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) + || ( ( (statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10)))) + ? 0 : -0xff; + if (!okflag){ + if ( (!no_search_trustee) || + !tru_eff_rights_exists(volume, xkpath, statb, TRUSTEE_T)) { + + if (soptions & VOL_OPTION_IS_PIPE) { + statb->st_size = 0x70000000|(statb->st_mtime&0xfffffff); + } + xstrcpy(nwpath->fn, (char*)dname); + XDPRINTF((5,0,"FOUND=:%s: attrib=0x%x", nwpath->fn, statb->st_mode)); + break; /* ready */ + } else + okflag = -0xff; } - } else okflag = 0; + } else okflag = -0xff; } XDPRINTF((6,0, "NAME=:%s: OKFLAG %d", name, okflag)); } /* if */ } /* while */ closedir(f); - } /* if */ + } else okflag=-0x89; /* no search rights */ return(okflag); } @@ -706,7 +671,9 @@ static DIR *give_dh_f(DIR_HANDLE *dh) { if (!dh->f) { *(dh->kpath) = '\0'; + seteuid(0); dh->f = opendir(dh->unixname); + reseteuid(); } dh->timestamp=time(NULL); /* tnx to Andrew Sapozhnikov */ return(dh->f); @@ -724,8 +691,11 @@ static void release_dh_f(DIR_HANDLE *dh, int expire) static int get_dh_entry(DIR_HANDLE *dh, uint8 *search, + int size_search, int *sequence, int attrib, + char *unixname, + int size_unixname, struct stat *statb) /* returns 1 if OK and 0 if not OK */ @@ -736,25 +706,25 @@ static int get_dh_entry(DIR_HANDLE *dh, if (f != (DIR*)NULL) { struct dirent *dirbuff; uint8 entry[256]; - strmaxcpy(entry, search, 255); + xstrcpy(entry, search); if ( (uint16)*sequence == MAX_U16) *sequence = 0; if (*sequence < dh->sequence || ((long)dh->dirpos) < 0L) { dh->dirpos = (off_t)0; dh->sequence = 0; } - seekdir(f, dh->dirpos); + SEEKDIR(f, dh->dirpos); if (dh->sequence != *sequence) { while (dh->sequence < *sequence) { if (NULL == readdir(f)) { - dh->dirpos = telldir(f); + dh->dirpos = TELLDIR(f); release_dh_f(dh, 1); return(0); } dh->sequence++; } - dh->dirpos = telldir(f); + dh->dirpos = TELLDIR(f); } XDPRINTF((5,0,"get_dh_entry seq=0x%x, attrib=0x%x path:%s:, entry:%s:", *sequence, attrib, dh->unixname, entry)); @@ -767,21 +737,29 @@ static int get_dh_entry(DIR_HANDLE *dh, uint8 dname[256]; xstrcpy(dname, name); unix2doscharset(dname); - okflag = (name[0] != '.' && ( - (!strcmp((char*)dname, (char*)entry)) || - (entry[0] == '*' && entry[1] == '\0') - || fn_dos_match(dname, entry, dh->vol_options))); + okflag = (name[0] != '.' && + ( (!strcmp((char*)dname, (char*)entry)) + || fn_dos_match(dname, entry, dh->vol_options))); if (okflag) { - strcpy(dh->kpath, (char*)name); + strmaxcpy(dh->kpath, (char*)name, + sizeof(dh->unixname) - (int)(dh->kpath-dh->unixname) -1 ); XDPRINTF((5,0,"get_dh_entry Name=%s unixname=%s", name, dh->unixname)); if (!s_stat(dh->unixname, statb, NULL)) { okflag = ( (( (statb->st_mode & S_IFMT) == S_IFDIR) && (attrib & 0x10)) || (((statb->st_mode & S_IFMT) != S_IFDIR) && !(attrib & 0x10))); + + /* mst:15-Apr-00 */ + if (okflag && dh->no_search_trustee + && tru_eff_rights_exists(dh->volume, dh->unixname, statb, TRUSTEE_T)) + okflag=0; + if (okflag){ - strcpy((char*)search, (char*)dname); + if (unixname) + strmaxcpy(unixname, dh->unixname, size_unixname-1); + strmaxcpy((char*)search, (char*)dname, size_search-1); break; /* ready */ } } else okflag = 0; @@ -790,18 +768,18 @@ static int get_dh_entry(DIR_HANDLE *dh, } /* while */ dh->kpath[0] = '\0'; *sequence = dh->sequence; - dh->dirpos = telldir(f); + dh->dirpos = TELLDIR(f); release_dh_f(dh, (dirbuff==NULL)); } /* if */ return(okflag); } -static void conn_build_path_fn( uint8 *vol, - uint8 *path, - uint8 *fn, - int *has_wild, - uint8 *data, - int len) +static void conn_build_path_fn(uint8 *vol, + uint8 *path, + uint8 *fn, + int *has_wild, + uint8 *data, + int len) /* is called from build_path */ { @@ -812,7 +790,8 @@ static void conn_build_path_fn( uint8 *vol, while (len-- && *data){ if (*data == 0xae) *p1++ = '.'; else if (*data == 0xaa|| *data == '*' ) { - *p1++ = '*'; + /* *p1++ = '*'; */ + *p1++ = *data; (*has_wild)++; } else if (*data == 0xbf|| *data == '?' ) { *p1++ = '?'; @@ -821,7 +800,7 @@ static void conn_build_path_fn( uint8 *vol, *p1++ = '/'; p = p1; } else if (*data == ':') { /* extract volume */ - int len = (int) (p1 - path); + int len = (int)(p1 - path); memcpy(vol, path, len); vol[len] = '\0'; up_fn(vol); @@ -832,10 +811,10 @@ static void conn_build_path_fn( uint8 *vol, *p1 = '\0'; if (fn != NULL) { /* if with filename */ if (p != NULL){ /* exist directory-path */ - strcpy((char*)fn, (char*)p); + strmaxcpy((char*)fn, (char*)p, 255); *p = '\0'; } else { /* only filename */ - strcpy((char*)fn, (char*)path); + strmaxcpy((char*)fn, (char*)path, 255); *path= '\0'; } } @@ -854,7 +833,9 @@ static int build_path( NW_PATH *path, */ { uint8 vol[256]; - conn_build_path_fn(vol, path->path, + if (len > 255) len = 255; + conn_build_path_fn(vol, + path->path, (only_dir) ? (uint8)NULL : path->fn, &(path->has_wild), @@ -883,13 +864,10 @@ static int build_path( NW_PATH *path, return(0); } -static int nw_path_ok(NW_PATH *nwpath, struct stat *stbuff) +static int nw_path_directory_is_ok(NW_PATH *nwpath, struct stat *stbuff) /* returns UNIX inode of path */ { - int j = 0; - NW_DIR *d=&(dirs[0]); int result=0; - if ((!act_obj_id) && !(entry8_flags & 1)) { if (nwpath->volume) result = -0x9c; /* wrong path, only volume 0 is OK */ @@ -904,22 +882,11 @@ static int nw_path_ok(NW_PATH *nwpath, struct stat *stbuff) result=-0x9c; } } - - if (!result) { - while (j++ < (int)used_dirs){ - if (d->inode && d->volume == nwpath->volume - && !strcmp((char*)nwpath->path, (char*)d->path)){ - stbuff->st_ino = d->inode; - stbuff->st_dev = d->dev; - return(d->inode); - } - d++; - } /* while */ - if (!s_stat(build_unix_name(nwpath, 1 | 2 ), stbuff, NULL) + if (!result && !s_stat(build_unix_name(nwpath, 1 | 2 ), stbuff, NULL) && S_ISDIR(stbuff->st_mode)) - return(stbuff->st_ino); + return(stbuff->st_ino); + else if (!result) result = -0x9c; /* wrong path */ - } XDPRINTF((4,0x10, "NW_PATH_OK failed:`%s`", conn_get_nwpath_name(nwpath))); return(result); } @@ -935,7 +902,7 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */ uint8 *ppp=nwpath->path; int completition=0; - strcpy((char*)searchpath, (char*)ppp); /* save path */ + xstrcpy(searchpath, (char*)ppp); /* save path */ if (nwpath->volume > -1) { /* absolute path */ *ppp= '\0'; @@ -948,7 +915,8 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */ *ppp = '\0'; } else { /* get path from dir_handle */ NW_VOL *v = &nw_volumes[nwpath->volume]; - strcpy((char*)ppp, (char*)dirs[dir_handle].path); + strmaxcpy((char*)ppp, (char*)dirs[dir_handle].path, + sizeof(nwpath->path) - (int)(ppp-nwpath->path) -1 ); if (v->options & VOL_OPTION_IGNCASE) ppp += strlen(ppp); } @@ -1030,9 +998,10 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */ int pathlen = strlen(nwpath->path); int fnlen = strlen(nwpath->fn); memcpy(unixname, v->unixname, v->unixnamlen); - strcpy(pp, nwpath->path); + strmaxcpy(pp, nwpath->path, sizeof(unixname) - v->unixnamlen-1); if (fnlen) - strcpy(pp+pathlen, nwpath->fn); + strmaxcpy(pp+pathlen, nwpath->fn, + sizeof(unixname) - v->unixnamlen - pathlen-1 ); dos2unixcharset(pp); pp += offset; pathlen -= offset; @@ -1044,12 +1013,12 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */ memcpy(nwpath->fn, pp+pathlen, fnlen); } } else return(-0x98); /* wrong volume */ - completition = nw_path_ok(nwpath, stbuff); + completition = nw_path_directory_is_ok(nwpath, stbuff); } return(completition); } -static int conn_get_kpl_path(NW_PATH *nwpath, struct stat *stbuff, +static int conn_get_kpl_path(NW_PATH *nwpath, struct stat *stbuff, int dirhandle, uint8 *data, int len, int only_dir) /* * if ok then the inode of dir will be returned @@ -1063,10 +1032,10 @@ static int conn_get_kpl_path(NW_PATH *nwpath, struct stat *stbuff, return(completition); } -int conn_get_full_path(int dirhandle, uint8 *data, int len, - uint8 *fullpath) +int conn_get_full_path(int dirhandle, uint8 *data, int len, + uint8 *fullpath, int size_fullpath) /* returns path in form VOLUME:PATH */ -{ +{ NW_PATH nwpath; struct stat stbuff; int result = build_path(&nwpath, data, len, 0); @@ -1075,23 +1044,26 @@ int conn_get_full_path(int dirhandle, uint8 *data, int len, result = build_dir_name(&nwpath, &stbuff, dirhandle); if (result > -1) { uint8 *p=(*nwpath.path=='/') ? nwpath.path+1 : nwpath.path; - int len=sprintf(fullpath, "%s:%s", + int len = slprintf(fullpath, size_fullpath-1, "%s:%s", nw_volumes[nwpath.volume].sysname, p); - if (nwpath.fn[0]) { - if (*p) fullpath[len++]='/'; - strcpy(fullpath+len, nwpath.fn); - } - result=len+strlen(nwpath.fn); + if (len > 0) { + if (nwpath.fn[0]) { + if (*p) fullpath[len++]='/'; + strmaxcpy(fullpath+len, nwpath.fn, size_fullpath - len -1); + } + result = len + strlen(nwpath.fn); + } else result = -0x9c; /* wrong path */ } XDPRINTF((1, 0, "conn_get_full_path: result=%d,(0x%x),`%s`", result, result, fullpath)); return(result); } int conn_get_kpl_unxname(char *unixname, + int size_unixname, int dirhandle, uint8 *data, int len) /* - * gives you the unixname of dirhandle + path + * gives the unixname of dirhandle + path * returns volumenumber, or < 0 if error */ { @@ -1102,7 +1074,7 @@ int conn_get_kpl_unxname(char *unixname, completition = build_dir_name(&nwpath, &stbuff, dirhandle); if (completition > -1) { if (unixname) - strcpy(unixname, build_unix_name(&nwpath, 0)); + strmaxcpy(unixname, build_unix_name(&nwpath, 0), size_unixname-1); completition=nwpath.volume; } XDPRINTF((5, 0, "conn_get_kpl_unxname: completition=0x%x", completition)); @@ -1161,133 +1133,17 @@ time_t nw_2_un_time(uint8 *d, uint8 *t) return(mktime(&s_tm)); } -#if !NEW_ATTRIB_HANDLING -int un_nw_attrib(struct stat *stb, int attrib, int mode) -/* mode: 0 = un2nw , 1 = nw2un */ -{ - /* Attribute */ - /* 0x01 readonly */ - /* 0x02 hidden */ - /* 0x04 System */ - /* 0x10 IS_DIR */ - /* 0x20 Archive Flag */ - /* 0x80 Sharable */ /* TLINK (TCC 2.0) don't like it ???? */ - - int is_dir=S_ISDIR(stb->st_mode); - - if (!mode) { - /* UNIX access -> NW access */ - - if (!is_dir) { - attrib = FILE_ATTR_A; - } else { - attrib = FILE_ATTR_DIR; - } - if (act_uid) { - /* if not root */ - int acc=get_real_access(stb); - if (!(acc & W_OK)) { - attrib |= FILE_ATTR_R; /* RO */ - } - if (!(acc & R_OK)) { - attrib |= FILE_ATTR_H; /* We say hidden here */ - } - } - /* only shared if gid == gid && x Flag */ - if (!is_dir) { - if ((act_gid == stb->st_gid) && (stb->st_mode & S_IXGRP)) - attrib |= FILE_ATTR_SHARE; /* shared flag */ - } - return(attrib); - } else { - /* NW access -> UNIX access */ - int mode = S_IRUSR | S_IRGRP; - -#if 0 - /* this is sometimes very BAD */ - if (attrib & FILE_ATTR_H) /* hidden */ - stb->st_mode &= ~mode; - else -#endif - stb->st_mode |= mode; - - mode = S_IWUSR | S_IWGRP; - if ((!is_dir) && (attrib & FILE_ATTR_R)) /* R/O */ - /* we do not set directories to readonly: 28-Nov-97 */ - stb->st_mode &= ~mode; - else - stb->st_mode |= mode; - - if (!is_dir) { - if (attrib & FILE_ATTR_SHARE) /* Shared */ - stb->st_mode |= S_IXGRP; - else - stb->st_mode &= ~S_IXGRP; - } - return(stb->st_mode); - } -} -#endif - -int un_nw_rights(struct stat *stb) -/* returns eff rights of file/dir */ -/* needs some more work */ -{ - /* int rights=0xfb; first all rights, but not TRUSTEE_O */ - int rights=0xff; /* first all, pconsole needs TRUSTEE_O */ - if (act_uid) { - /* if not root */ - int is_dir = S_ISDIR(stb->st_mode); - int acc=get_real_access(stb); - int norights= TRUSTEE_A; /* no access control rights */ - if (!(acc & W_OK)) { - if (is_dir) { - norights |= TRUSTEE_C; - norights |= TRUSTEE_E; - } else { - norights |= TRUSTEE_W; /* RO */ - } - } - if (!(acc & R_OK)) { - if (is_dir) { - norights |= TRUSTEE_F; /* SCAN */ - } else { - norights |= TRUSTEE_R; /* Not for Reading */ - } - } - rights &= ~norights; - } else rights|= TRUSTEE_S; /* Supervisor */ - return(rights); -} - -static int get_file_attrib(NW_FILE_INFO *f, struct stat *stb, +static int get_file_attrib(NW_FILE_INFO *f, char *unixname, struct stat *stb, NW_PATH *nwpath) { - int voloptions=get_volume_options(nwpath->volume); uint32 dwattrib; strncpy((char*)f->name, (char*)nwpath->fn, sizeof(f->name)); - f->attrib=0; /* d->name could be too long */ + f->attrib[0]=0; /* d->name could be too long */ up_fn(f->name); -#if NEW_ATTRIB_HANDLING - dwattrib = get_nw_attrib_dword(stb, voloptions); - f->attrib = (uint8)(dwattrib & 0xff); -# if 0 - /* is this OK or next ??? */ - dwattrib >>=8; - f->ext_attrib = (uint8)(dwattrib & 0xff); -# else - f->ext_attrib = 0; -# endif -#else - if (voloptions & VOL_OPTION_IS_PIPE) - f->attrib = FILE_ATTR_SHARE; - else - f->attrib = (uint8) un_nw_attrib(stb, 0, 0); - XDPRINTF((5,0, "get_file_attrib = 0x%x of ,%s, uid=%d, gid=%d", - (int)f->attrib, conn_get_nwpath_name(nwpath), - stb->st_uid, stb->st_gid)); - f->ext_attrib = 0; -#endif + + dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb); + U16_TO_16(dwattrib, f->attrib); + un_date_2_nw(stb->st_mtime, f->create_date, 1); un_date_2_nw(stb->st_atime, f->acces_date, 1); un_date_2_nw(stb->st_mtime, f->modify_date, 1); @@ -1296,27 +1152,19 @@ static int get_file_attrib(NW_FILE_INFO *f, struct stat *stb, return(1); } -static int get_dir_attrib(NW_DIR_INFO *d, struct stat *stb, + +static int get_dir_attrib(NW_DIR_INFO *d, char *unixname, struct stat *stb, NW_PATH *nwpath) { - int voloptions=get_volume_options(nwpath->volume); + uint32 dwattrib; XDPRINTF((5,0, "get_dir_attrib of %s", conn_get_nwpath_name(nwpath))); strncpy((char*)d->name, (char*)nwpath->fn, sizeof(d->name)); - d->attrib=0; /* d->name could be too long */ + d->attrib[0]=0; /* d->name could be too long */ up_fn(d->name); - -#if NEW_ATTRIB_HANDLING - d->attrib = (uint8)get_nw_attrib_dword(stb, voloptions); - - d->ext_attrib = (uint8) un_nw_rights(stb); /* effektive rights ?? */ -#else - d->attrib = (uint8) un_nw_attrib(stb, 0, 0); -# if 0 /* changed: 02-Nov-96 */ - d->ext_attrib = 0xff; /* effektive rights ?? */ -# else - d->ext_attrib = (uint8) un_nw_rights(stb); /* effektive rights ?? */ -# endif -#endif + + dwattrib = get_nw_attrib_dword(nwpath->volume, unixname, stb); + U16_TO_16(dwattrib, d->attrib); + un_date_2_nw(stb->st_mtime, d->create_date, 1); un_time_2_nw(stb->st_mtime, d->create_time, 1); U32_TO_BE32(get_file_owner(stb), d->owner_id); @@ -1329,68 +1177,317 @@ static int get_dir_attrib(NW_DIR_INFO *d, struct stat *stb, static int do_delete_file(NW_PATH *nwpath, FUNC_SEARCH *fs) { char unname[256]; - strcpy(unname, build_unix_name(nwpath, 0)); + xstrcpy(unname, build_unix_name(nwpath, 0)); XDPRINTF((5,0,"DELETE FILE unname:%s:", unname)); - return(nw_unlink(nwpath->volume, unname)); + return(nw_unlink_node(nwpath->volume, unname, &(fs->statb))); } -int nw_delete_datei(int dir_handle, uint8 *data, int len) +int nw_delete_files(int dir_handle, int searchattrib, uint8 *data, int len) { NW_PATH nwpath; struct stat stbuff; int completition = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 0); if (completition > -1) { - completition = func_search_entry(&nwpath, 0x6, do_delete_file, NULL); + completition = func_search_entry(&nwpath, searchattrib, do_delete_file, NULL); if (completition < 0) return(completition); else if (!completition) return(-0xff); } return(completition); } +#if 1 +/* new since 22-May-99, 0.99.pl16 */ +/* corrected 03-Jun-99, 0.99.pl17 */ +typedef struct { + NW_PATH destpath; + struct stat statbuf; +} MV_FILES_STRUCT; + +static int do_mv_file(NW_PATH *nwpath, FUNC_SEARCH *fs) +/* rename one File */ +{ + char unsource[256]; + int result=0; + MV_FILES_STRUCT *nws=(MV_FILES_STRUCT*)fs->ubuf; + struct stat statb; + xstrcpy(unsource, build_unix_name(nwpath, 0)); + + if (stat(unsource, &statb) || + tru_eff_rights_exists(nwpath->volume, unsource, &statb, + TRUSTEE_W|TRUSTEE_M|TRUSTEE_R)) + result=-0x8b; + else if ( !S_ISDIR(fs->statb.st_mode) /* file */ && !(entry8_flags&0x80) && + -1 == share_file(fs->statb.st_dev, fs->statb.st_ino, 0x10f, 2) ) + result = -0x8a; /* NO Rename Privileges, file is shared open */ + /* patch from Przemyslaw Czerpak */ + if (!result) { + /* sourcefile is ok, now try to move to destfile */ + char undest[256]; + char saved_fn[256]; + + uint8 *frompath = nwpath->fn; + uint8 *topath = nws->destpath.fn; + uint8 *otopath = saved_fn; + uint8 c; + + /* we must save destpath, because perhaps we must modify it */ + strmaxcpy(saved_fn, nws->destpath.fn, sizeof(saved_fn)-1); + + while ((0 != (c = *otopath++))) { + switch (c) { + case '?' : + case 0xbf: + if ( *frompath + && *frompath != '.' + && *frompath != 0xae ) + *topath++ = *frompath++; + break; + + case '.' : + case 0xae: + while (*frompath + && *frompath != '.' + && *frompath != 0xae ) + frompath++; + if (*frompath) + frompath++; + /* only append '.' if not at end */ + if (*otopath) + *topath++='.'; + break; + + default: + if (*frompath && *frompath != '.' && *frompath != 0xae) + frompath++; + *topath++=c; + break; + + } /* switch */ + } /* while */ + *topath='\0'; + xstrcpy(undest, build_unix_name(&nws->destpath, 0)); + /* now restore destpath.fn */ + xstrcpy(nws->destpath.fn, saved_fn); + + seteuid(0); + if (entry8_flags & 0x4) /* new: 20-Nov-96 */ + result = unx_mvfile_or_dir(unsource, undest); + else + result = unx_mvfile(unsource, undest); + reseteuid(); + + switch (result) { + case 0 : break; /* ok */ + case EEXIST : result = -0x92; break; /* allready exist */ + case EXDEV : result = -0x9a; break; /* cross device */ + case EROFS : result = -0x8b; break; /* no rights */ + default : result = -0xff; break; /* unknown error */ + } + } + + return(result); +} + +int nw_mv_files(int searchattrib, + int sourcedirhandle, uint8 *sourcedata, int sourcedatalen, + int destdirhandle, uint8 *destdata, int destdatalen) +{ + NW_PATH nwpath; + struct stat stbuff; + int completition = conn_get_kpl_path(&nwpath, &stbuff, sourcedirhandle, sourcedata, sourcedatalen, 0); + if (completition > -1) { + FUNC_SEARCH fs; + MV_FILES_STRUCT mvs; + completition=conn_get_kpl_path(&mvs.destpath, &mvs.statbuf, + destdirhandle, destdata, destdatalen, 0); + if (completition > -1) { + char destpath[256]; + completition=0; + xstrcpy(destpath, build_unix_name(&mvs.destpath, 1)); + if (tru_eff_rights_exists(mvs.destpath.volume, destpath, + &mvs.statbuf, TRUSTEE_W)) + completition=-0x8b; + /* now destpath is tested to be writable */ + } + if (completition > -1) { + fs.ubuf = (uint8*)&mvs; + completition = func_search_entry(&nwpath, searchattrib, do_mv_file, &fs); + if (completition < 0) return(completition); + else if (!completition) return(-0xff); + else return(0); + } + } + return(completition); +} + + +#else /* old version (before 22-May-99, 0.99.pl15 ) */ + +/* "Resolve" string 'topath' (possible with wildcards '?') using + * 'frompath' as source for substitution. Make changes directly in + * 'topath'. Return new length of topath (equal or less than original value) + * Routine from: Andrew Sapozhnikov + */ + +static int apply_wildcards (uint8 *frompath, int flen, uint8 *topath, int tlen) +{ + int i,tlen2; + uint8 c,*topath2; + + for (i=flen; i > 0; i--) { + c=frompath[i-1]; + if (c == ':' || c == '\\' || c == '/') break; + } + frompath+=i; + flen-=i; + + for (i=tlen; i > 0; i--) { + c=topath[i-1]; + if(c == ':' || c == '\\' || c == '/') break; + } + topath2=(topath+=i); + tlen2=tlen-i; + + while (tlen2--) { + switch (c=*topath2++) { + case '?': + case 0xbf: + if (flen && *frompath != '.' && *frompath != 0xae) { + *topath++ = *frompath++; + flen--; + } else tlen--; + break; + case '.': + case 0xae: + while (flen && *frompath != '.' && *frompath != 0xae) { + frompath++; + flen--; + } + if (flen) { + frompath++; + flen--; + } + *topath++=c; + break; + default: + if (flen && *frompath != '.' && *frompath != 0xae) { + frompath++; + flen--; + } + *topath++=c; + } + } + return tlen; +} + +int mv_file(int qdirhandle, uint8 *q, int qlen, + int zdirhandle, uint8 *z, int zlen) +{ + NW_PATH quellpath; + struct stat qstbuff; + NW_PATH zielpath; + struct stat zstbuff; + int completition; + zlen=apply_wildcards(q, qlen, z, zlen); + completition=conn_get_kpl_path(&quellpath, &qstbuff, qdirhandle, q, qlen, 0); + + if (completition > -1) { + char qfn[256]; + xstrcpy(qfn, build_unix_name(&quellpath,0)); + completition=conn_get_kpl_path(&zielpath, &zstbuff, zdirhandle, z, zlen, 0); + if (completition > -1) { + char zpath[256]; + completition=0; + xstrcpy(zpath, build_unix_name(&zielpath, 1)); + if (stat(qfn, &qstbuff) || + tru_eff_rights_exists(quellpath.volume, qfn, &qstbuff, + TRUSTEE_W|TRUSTEE_M|TRUSTEE_R)) + completition=-0x8b; + else if (tru_eff_rights_exists(zielpath.volume, zpath, &zstbuff, + TRUSTEE_W)) + completition=-0x8b; + } + if (!completition){ + char unziel[256]; + xstrcpy(unziel, build_unix_name(&zielpath,0)); + + seteuid(0); + if (entry8_flags & 0x4) /* new: 20-Nov-96 */ + completition = unx_mvfile_or_dir(qfn, unziel); + else + completition = unx_mvfile(qfn, unziel); + reseteuid(); + + switch (completition) { + case 0 : break; + case EEXIST : completition = -0x92; break; /* allready exist */ + case EXDEV : completition = -0x9a; break; /* cross device */ + case EROFS : completition = -0x8b; break; /* no rights */ + default : completition = -0xff; + } + } + } + return(completition); +} +#endif + static int do_set_file_info(NW_PATH *nwpath, FUNC_SEARCH *fs) { char unname[256]; int result=0; NW_FILE_INFO *f=(NW_FILE_INFO*)fs->ubuf; - int voloptions; - strcpy(unname, build_unix_name(nwpath, 0)); - if ((voloptions = get_volume_options(nwpath->volume)) & VOL_OPTION_IS_PIPE){ - ;; /* don't change 'pipe commands' */ - } else if (voloptions & VOL_OPTION_READONLY) { - result=(-0x8c); /* no modify rights */ - } else { + int voloptions = get_volume_options(nwpath->volume); + struct stat statb; + xstrcpy(unname, build_unix_name(nwpath, 0)); + if (!stat(unname, &statb)) { + if (S_ISFIFO(statb.st_mode) || (voloptions&VOL_OPTION_IS_PIPE)) + return(0); /* do nothing but report OK */ + if (tru_eff_rights_exists(nwpath->volume, unname, &statb, TRUSTEE_M)) + result=-0x8c; /* no modify rights */ + } else result=-0xff; + if (!result) { struct utimbuf ut; - struct stat statb; -#if PERSISTENT_SYMLINKS - S_STATB stb; -#endif ut.actime = ut.modtime = nw_2_un_time(f->modify_date, f->modify_time); - if (0 == (result=s_stat(unname, &statb, &stb))) { -#if NEW_ATTRIB_HANDLING - result = set_nw_attrib_byte(&statb, voloptions, (int) f->attrib); - if (result < 0 && !(f->attrib & FILE_ATTR_R)) { - result = s_chmod(unname, statb.st_mode | S_IWUSR, &stb); - if (!result) { - statb.st_mode |= S_IWUSR; - result = set_nw_attrib_byte(&statb, voloptions, (int)f->attrib); - } - } - if (!result) - result=s_utime(unname, &ut, &stb); -#else - if (0 == (result=s_utime(unname, &ut, &stb))){ - result = s_chmod(unname, - un_nw_attrib(&statb, (int)f->attrib, 1), &stb); - } -#endif + result=set_nw_attrib_word(nwpath->volume, unname, &statb, + (int)GET_16(f->attrib)); + if (!result) { + seteuid(0); + if (utime(unname, &ut)) + result= (-0x8c); /* no modify rights */ + reseteuid(); } - if (result) - result= (-0x8c); /* no modify rights */ } XDPRINTF((5,0,"set_file_info result=0x%x, unname:%s:", unname, -result)); return(result); } +static void free_dir_stuff(struct stat *stb, int complete) +{ + NW_DIR *d=&(dirs[0]); + int j = -1; + if (complete) { + while (++j < (int)used_dirs){ + if ( d->dev == stb->st_dev && + d->inode == stb->st_ino) + d->inode = 0; + d++; + } + j = -1; + } + while (++j < (int)anz_dirhandles){ + DIR_HANDLE *dh=&(dir_handles[j]); + if (dh && dh->dev == stb->st_dev && dh->inode == stb->st_ino) { + if (complete) + free_dir_handle(j+1); + else if (dh->f) { /* only close directories */ + /* needed to ask for null pointer, hint from Boris Popov, 21-Feb-99 */ + closedir(dh->f); + dh->f = (DIR*)NULL; + } + } + } +} + int nw_set_file_information(int dir_handle, uint8 *data, int len, int searchattrib, NW_FILE_INFO *f) { @@ -1416,7 +1513,6 @@ int nw_set_file_attributes(int dir_handle, uint8 *data, int len, struct stat stbuff; int completition=-0x9c; NW_PATH nwpath; - int voloptions; #if PERSISTENT_SYMLINKS S_STATB stb; #endif @@ -1425,87 +1521,173 @@ int nw_set_file_attributes(int dir_handle, uint8 *data, int len, completition = build_dir_name(&nwpath, &stbuff, dir_handle); } if (completition < 0) return(completition); - voloptions=get_volume_options(nwpath.volume); - strcpy(unname, build_unix_name(&nwpath, 2)); + xstrcpy(unname, build_unix_name(&nwpath, 2)); XDPRINTF((5,0,"set file attrib 0x%x, unname:%s:", newattrib, unname)); if (!s_stat(unname, &stbuff, &stb)){ -#if NEW_ATTRIB_HANDLING - int result = set_nw_attrib_byte(&stbuff, voloptions, newattrib); - if (result < 0 && !(newattrib & FILE_ATTR_R)) { - result = s_chmod(unname, stbuff.st_mode | S_IWUSR, &stb); - if (!result) { - stbuff.st_mode |= S_IWUSR; - result = set_nw_attrib_byte(&stbuff, voloptions, newattrib); - } - } -#else - int result = s_chmod(unname, un_nw_attrib(&stbuff, newattrib, 1), &stb); -#endif + int result = set_nw_attrib_byte(nwpath.volume, unname, &stbuff, newattrib); return( (result != 0) ? -0x8c : 0); /* no modify rights */ } return(-0x9c); /* wrong path */ } -int nw_creat_node(int volnr, uint8 *unname, int mode) +static int nw_rmdir(uint8 *unname) +{ + if (rmdir(unname)) { + if (errno == /*EEXIST*/ ENOTEMPTY) return(-0xa0); /* directory not empty */ + return(-0x8a); /* no privilegs */ + } + return(0); +} + +int nw_unlink_node(int volume, uint8 *unname, struct stat *stb) +{ + int result=-1; + uint32 attrib=get_nw_attrib_dword(volume, unname, stb); + /* first we look for attributes */ + if (attrib & (FILE_ATTR_R|FILE_ATTR_DELETE_INH)) + return(-0x8a); /* don't delete 'readonly' */ + if (tru_eff_rights_exists(volume, unname, stb, TRUSTEE_E)) + return(-0x8a); /* no delete rights */ + + if (S_ISDIR(stb->st_mode)) { /* directory */ + free_dir_stuff(stb, 0); + result=nw_rmdir(unname); + if (result==-0x8a){ /* no privilegs */ + seteuid(0); + result=nw_rmdir(unname); + reseteuid(); + } + if (!result) + free_dir_stuff(stb, 1); + } else { + /* changed by: Ingmar Thiemann + * because share_file() changed + */ + if (!(entry8_flags&0x10) && + -1 == share_file(stb->st_dev, stb->st_ino, 0x10f, 2)) + return(-0x8a); /* NO Delete Privileges, file is open */ + if (0 != (result=unlink(unname))){ + seteuid(0); + result=unlink(unname) ? -0x8a : 0; + reseteuid(); + } + } + if (!result) { + free_nw_ext_inode(volume, unname, stb->st_dev, stb->st_ino); + } + return(result); +} + +int nw_creat_node(int volume, uint8 *unname, int mode) /* creat file or directory, depending on mode */ /* mode & 0x1 == directory */ /* mode & 0x2 == creat/trunc */ +/* next is only for file creation, needed by some queue functions */ /* mode & 0x8 == ignore rights, try to open as root */ { struct stat stb; + uint8 path[260]; + uint8 *p=path+strlen(unname); + xstrcpy(path, unname); + while (p > path && *p != '/') --p; + if (p > path) { + *p='\0'; + if (stat(path, &stb)) return(-0x9c); + } else if (*p=='/') { + *(p+1)='.'; + *(p+2)='\0'; + if (stat(path, &stb)) return(-0x9c); + } else + return(-0x9c); + if (mode & 1) { /* directory */ - if (!mkdir(unname, 0777)) { - int umode_dir=get_volume_umode_dir(volnr); - if (umode_dir) { - if (umode_dir == -1) { /* we get parent dir */ - uint8 fn[260]; - strcpy(fn, unname); - strcat(fn, "/.."); - if (!stat(fn, &stb)) { - umode_dir=stb.st_mode; - } else return(0); - } - chmod(unname, umode_dir); + int result=-0xff; + if (!tru_eff_rights_exists(volume, path, &stb, TRUSTEE_C)){ + result=mkdir(unname, 0777); + if (result) { + seteuid(0); + if (0==(result=mkdir(unname, 0755))) + chown(unname, act_uid, act_gid); + reseteuid(); + } + if (result) + result=-0xff; + } else result=-0x84; /* no creat rights */ + if (!result) { + int umode_dir=get_volume_umode_dir(volume); + if (umode_dir) { + if (umode_dir == -1) /* we get parent dir */ + umode_dir=stb.st_mode; + seteuid(0); + chmod(unname, umode_dir); + reseteuid(); } - return(0); } + return(result); } else { /* file */ int fd=-1; - if (mode & 2) { - struct stat stbuff; - int voloptions = get_volume_options(volnr); - if (!stat(unname, &stbuff)) { /* exists */ - if (get_nw_attrib_dword(&stbuff, voloptions) & FILE_ATTR_R) - fd=-2; + struct stat stbuff; + int exist; + + seteuid(0); + exist=stat(unname, &stbuff) ? 0 : 1; + reseteuid(); + + if (!(mode&0x8)) { /* we must test for access */ + if (exist) { /* test for write rights */ + if (get_nw_attrib_dword(volume, unname, &stbuff) & FILE_ATTR_R) + return(-0x94); /* No write rights */ + if (tru_eff_rights_exists(volume, unname, &stbuff, TRUSTEE_W)) + return(-0x94); /* No write rights */ + } else { /* test for creat rights */ + if (tru_eff_rights_exists(volume, path, &stb, TRUSTEE_C)) + return(-0x84); /* No creat rights */ } - if (fd!=-2) - fd=open(unname, O_CREAT|O_TRUNC|O_RDWR, 0777); - } else - fd = creat(unname, 0777); - - if (fd < 0 && (mode & 8)) { /* creat always */ - if ( (!seteuid(0)) && (-1 < (fd = - open(unname, O_CREAT|O_TRUNC|O_RDWR, 0777)))) { - int umode_file=get_volume_umode_file(volnr); - close(fd); - chown(unname, act_uid, act_gid); - if (umode_file > 0) - chmod(unname, umode_file); + } + + if (mode & 2 || (exist && (mode&0x8)) ) { /* trunc */ + if (0 > (fd=open(unname, O_CREAT|O_TRUNC|O_RDWR, 0666))) { + seteuid(0); + if (-1 < (fd=open(unname, O_CREAT|O_TRUNC|O_RDWR, 0600))) + chown(unname, act_uid, act_gid); + reseteuid(); + } + } else if (!exist) { + if (0 > (fd = creat(unname, 0777))) { + seteuid(0); + if (-1 < (fd = creat(unname, 0751))) + chown(unname, act_uid, act_gid); reseteuid(); - return(0); } - reseteuid(); } if ( fd > -1 ) { - int umode_file=get_volume_umode_file(volnr); + int umode_file=get_volume_umode_file(volume); close(fd); - if (umode_file > 0) + if (umode_file > 0) chmod(unname, umode_file); return(0); - } + } } - return(-1); + return(-0xff); +} + +int nw_utime_node(int volume, uint8 *unname, struct stat *stb, + time_t t) +{ + if (!tru_eff_rights_exists(volume, unname, stb, TRUSTEE_M)){ + struct utimbuf ut; + ut.actime = ut.modtime = t; + if (!utime(unname, &ut)) + return(0); + seteuid(0); + if (!utime(unname, &ut)) { + reseteuid(); + return(0); + } + reseteuid(); + } + return(-0x8c); /* no modify privileges */ } int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode) @@ -1513,150 +1695,77 @@ int nw_mk_rd_dir(int dir_handle, uint8 *data, int len, int mode) NW_PATH nwpath; struct stat stbuff; int completition = conn_get_kpl_path(&nwpath, &stbuff, - dir_handle, data, len, !mode); + dir_handle, data, len, (mode) ? 0 : 1 ); if (completition > -1) { char unname[256]; - int voloptions; - strcpy(unname, build_unix_name(&nwpath, 2)); - if ((voloptions=get_volume_options(nwpath.volume)) & VOL_OPTION_READONLY) - return(mode ? -0x84 : -0x8a); - + xstrcpy(unname, build_unix_name(&nwpath, 2)); if (mode) { - XDPRINTF((5,0,"MKDIR dirname:%s:", unname)); - if (!nw_creat_node(nwpath.volume, unname, 1)) - return(0); - if (errno == EEXIST) - completition = -0xff; - else - completition = -0x84; /* No Create Priv.*/ /* -0x9f Direktory Aktive */ + completition=nw_creat_node(nwpath.volume, unname, 1); } else { /* rmdir */ - int j = -1; - if (get_nw_attrib_dword(&stbuff, voloptions) & FILE_ATTR_R) - return(-0x8a); /* don't delete 'readonly' */ - - while (++j < (int)anz_dirhandles){ - DIR_HANDLE *dh=&(dir_handles[j]); - if ( dh->dev == stbuff.st_dev && - dh->inode == stbuff.st_ino && dh->f != (DIR*) NULL) { - closedir(dh->f); - dh->f = (DIR*)NULL; - } - } - XDPRINTF((5,0,"RMDIR dirname:%s:", unname)); - - if (!rmdir(unname)) { - NW_DIR *d=&(dirs[0]); - j = 0; - while (j++ < (int)used_dirs){ - if ( d->dev == stbuff.st_dev && - d->inode == stbuff.st_ino) d->inode = 0; - d++; - } - j = -1; - while (++j < (int)anz_dirhandles){ - DIR_HANDLE *dh=&(dir_handles[j]); - if (dh->inode == completition) free_dir_handle(j+1); - } - free_nw_ext_inode(stbuff.st_dev, stbuff.st_ino); - completition = 0; - } else if (errno == EEXIST) - completition = -0xa0; /* dir not empty */ - else completition = -0x8a; /* No privilegs */ - } - } - return(completition); -} - -int mv_file(int qdirhandle, uint8 *q, int qlen, - int zdirhandle, uint8 *z, int zlen) -{ - NW_PATH quellpath; - struct stat qstbuff; - NW_PATH zielpath; - struct stat zstbuff; - int completition; - zlen=apply_wildcards(q, qlen, z, zlen); - completition=conn_get_kpl_path(&quellpath, &qstbuff, qdirhandle, q, qlen, 0); - - if (completition > -1) { - completition=conn_get_kpl_path(&zielpath, &zstbuff, zdirhandle, z, zlen, 0); - if (completition > -1) { - int optq = get_volume_options(quellpath.volume); - int optz = get_volume_options(zielpath.volume); - if ((optq & VOL_OPTION_IS_PIPE) || - (optz & VOL_OPTION_IS_PIPE)) completition = -0x8b; - else if ((optq & VOL_OPTION_READONLY) || - (optz & VOL_OPTION_READONLY)) completition = -0x8b; - } - if (completition > -1){ - char unquelle[256]; - char unziel[256]; - strcpy(unquelle, build_unix_name(&quellpath,0)); - strcpy(unziel, build_unix_name(&zielpath,0)); - if (entry8_flags & 0x4) /* new: 20-Nov-96 */ - completition = unx_mvfile_or_dir(unquelle, unziel); + if (!stat(unname, &stbuff)) + completition=nw_unlink_node(nwpath.volume, unname, &stbuff); else - completition = unx_mvfile(unquelle, unziel); - switch (completition) { - case 0 : break; - case EEXIST : completition = -0x92; break; /* allready exist */ - case EXDEV : completition = -0x9a; break; /* cross device */ - case EROFS : completition = -0x8b; break; /* no rights */ - default : completition = -0xff; - } + completition=-0x9c; } } return(completition); } -int mv_dir(int dir_handle, uint8 *q, int qlen, - uint8 *z, int zlen) + +int mv_dir(int dir_handle, uint8 *sourcedata, int sourcedatalen, + uint8 *destdata, int destdatalen) { NW_PATH quellpath; struct stat qstbuff; NW_PATH zielpath; -#if 0 - struct stat zstbuff; -#endif - int completition=conn_get_kpl_path(&quellpath, &qstbuff, dir_handle, q, qlen, 0); + int completition=conn_get_kpl_path(&quellpath, &qstbuff, dir_handle, + sourcedata, sourcedatalen, 0); if (completition > -1){ -#if 1 - /* I do not know anymore why I did these ??? */ + char qfn[256]; + char zpath[256]; + struct stat zstbuff; + completition = 0; + xstrcpy(qfn, build_unix_name(&quellpath,0)); memcpy(&zielpath, &quellpath, sizeof(NW_PATH)); - strmaxcpy(zielpath.fn, z, zlen); + strmaxcpy(zielpath.fn, destdata, destdatalen); - /* ----------- now I know again why I did these ----- */ + /* patch from Sven Norinder :09-Nov-96 */ + if (get_volume_options(zielpath.volume) & VOL_OPTION_DOWNSHIFT) + down_fn(zielpath.fn); + else + up_fn(zielpath.fn); + +#if 0 + /* this is not possible ---- */ + completition=conn_get_kpl_path(&zielpath, &zstbuff, dir_handle, destdata, destdatalen, 0); + /* ----------- because ----- */ /* for example the novell rendir.exe does something like this * 0x0,0xd,0xf,0x0,0x7,'T','M','P',':','\','I','I',0x2,'K','K' * no dirhandle, qpath = fullpath, zpath = only name */ -#else - /* and NOT these, perhaps this will also be ok ?! -- TODO -- */ - completition=conn_get_kpl_path(&zielpath, &zstbuff, dir_handle, z, zlen, 0); #endif - if (completition > -1) { - int optq = get_volume_options(quellpath.volume); - int optz = get_volume_options(zielpath.volume); - if ((optq & VOL_OPTION_IS_PIPE) || - (optz & VOL_OPTION_IS_PIPE)) completition = -0x8b; - else if ((optq & VOL_OPTION_READONLY) || - (optz & VOL_OPTION_READONLY)) completition = -0x8b; - /* patch from Sven Norinder :09-Nov-96 */ - else if (optz & VOL_OPTION_DOWNSHIFT) - down_fn(zielpath.fn); - else - up_fn(zielpath.fn); - } + + xstrcpy(zpath, build_unix_name(&zielpath, 1)); + if (stat(qfn, &qstbuff) || + tru_eff_rights_exists(quellpath.volume, qfn, &qstbuff, + TRUSTEE_W|TRUSTEE_M|TRUSTEE_R)) + completition=-0x8b; + else if (stat(zpath, &zstbuff) || + tru_eff_rights_exists(zielpath.volume, zpath, &zstbuff, + TRUSTEE_W)) + completition=-0x8b; + if (completition > -1){ int result; - char unquelle[256]; char unziel[256]; - strcpy(unquelle, build_unix_name(&quellpath, 0)); - strcpy(unziel, build_unix_name(&zielpath, 0)); + xstrcpy(unziel, build_unix_name(&zielpath, 0)); - result = unx_mvdir((uint8 *)unquelle, (uint8 *)unziel); - XDPRINTF((2,0, "rendir result=%d, '%s'->'%s'", - result, unquelle, unziel)); + seteuid(0); + result = unx_mvdir((uint8 *)qfn, (uint8 *)unziel); + reseteuid(); + + XDPRINTF((4,0, "rendir result=%d, '%s'->'%s'", + result, qfn, unziel)); if (!result) completition = 0; else { @@ -1672,7 +1781,7 @@ int mv_dir(int dir_handle, uint8 *q, int qlen, } static int change_dir_entry( NW_DIR *dir, int volume, - uint8 *path, + uint8 *path, int dev, ino_t inode, int driveletter, int is_temp, int new_entry, int task) @@ -1737,7 +1846,7 @@ int nw_init_connect(void) NW_DIR *d = &(dirs[0]); int namspace_max_baseh=0; int namspace_max_searchh=0; - strcpy((char*)nwlogin.path, (char*)login); + xstrcpy(nwlogin.path, (char*)login); nwlogin.fn[0] = '\0'; nwlogin.volume = 0; @@ -1757,7 +1866,7 @@ int nw_init_connect(void) if (connect_is_init) { k = 0; - while (k++ < anz_dirhandles) + while (k++ < anz_dirhandles) free_dir_handle(k); } else connect_is_init++; @@ -1788,13 +1897,15 @@ int nw_init_connect(void) if (i>1) max_burst_send_size=sendsize; } + } else if (what == 31) { /* entry31_flags */ + entry31_flags = hextoi((char*)buff); } else if (50 == what) { init_nwfname(buff); } else if (63 == what) { /* MAX_DIR_BASE */ namspace_max_baseh=atoi(buff); } else if (68 == what) { /* USE_MMAP */ use_mmap=atoi(buff); - } else if (80 == what) { + } else if (80 == what) { namspace_max_searchh=atoi(buff); } else if (what == 103) { /* Debug */ get_debug_level(buff); @@ -1813,10 +1924,11 @@ int nw_init_connect(void) down_fn(nwlogin.path); if (stat(build_unix_name(&nwlogin, 0), &stbuff)) { errorp(1, "Stat error LOGIN Directory, Abort !!", - "UnixPath=`%s`", build_unix_name(&nwlogin, 0)); + "UnixPath=`%s`, nwlogin.path=%s, nwlogin.fn=%s", + build_unix_name(&nwlogin, 0), nwlogin.path, nwlogin.fn ); return(-1); } - (void)change_dir_entry(&(dirs[0]), 0, nwlogin.path, + (void)change_dir_entry(&(dirs[0]), 0, nwlogin.path, stbuff.st_dev, stbuff.st_ino, 0, 0, 1, 0); /* first Handle must be known und must not be temp */ @@ -1895,7 +2007,7 @@ int xinsert_new_dir(int volume, uint8 *path, int dev, int inode, int drive, int } else return(-0x9d); /* no dir Handles */ } -static int insert_new_dir(NW_PATH *nwpath, int dev, int inode, +static int insert_new_dir(NW_PATH *nwpath, int dev, int inode, int drive, int is_temp, int task) { return(xinsert_new_dir(nwpath->volume, nwpath->path, @@ -1915,21 +2027,25 @@ int nw_search(uint8 *info, uint32 *fileowner, nwpath.path, nwpath.fn, completition)); if (completition > -1) { struct stat stbuff; - if (get_dir_entry(&nwpath, + completition=get_dir_entry(&nwpath, &searchsequence, search_attrib, - &stbuff)){ + &stbuff); + if (!completition) { + char unixname[300]; + xstrcpy(unixname, build_unix_name(&nwpath, 0)); if ( S_ISDIR(stbuff.st_mode) ) { - get_dir_attrib((NW_DIR_INFO*)info, &stbuff, + get_dir_attrib((NW_DIR_INFO*)info, unixname, &stbuff, &nwpath); } else { - get_file_attrib((NW_FILE_INFO*)info, &stbuff, + get_file_attrib((NW_FILE_INFO*)info, unixname, &stbuff, &nwpath); } if (fileowner) *fileowner = get_file_owner(&stbuff); return(searchsequence); - } else return(-0xff); /* not found */ - } else return(completition); /* wrong path */ + } + } + return(completition); } int nw_dir_get_vol_path(int dirhandle, uint8 *path) @@ -1961,22 +2077,30 @@ int nw_dir_search(uint8 *info, build_path(&nwpath, data, len, 0); if (dirhandle > 0 && --dirhandle < anz_dirhandles){ DIR_HANDLE *dh = &(dir_handles[dirhandle]); + char unixname[300]; struct stat stbuff; if (dh->vol_options & VOL_OPTION_DOWNSHIFT) { down_fn(nwpath.fn); } else { up_fn(nwpath.fn); } + nwpath.volume=dh->volume; if (get_dh_entry(dh, nwpath.fn, + sizeof(nwpath.fn), &searchsequence, search_attrib, + unixname, + sizeof(unixname), &stbuff)){ + if ( S_ISDIR(stbuff.st_mode) ) { - get_dir_attrib((NW_DIR_INFO*)info, &stbuff, + get_dir_attrib((NW_DIR_INFO*)info, unixname, &stbuff, &nwpath); } else { - get_file_attrib((NW_FILE_INFO*)info, &stbuff, + if (dh->vol_options & VOL_OPTION_IS_PIPE) + stbuff.st_size = 0x70000000|(stbuff.st_mtime&0xfffffff); + get_file_attrib((NW_FILE_INFO*)info, unixname, &stbuff, &nwpath); } return(searchsequence); @@ -1990,17 +2114,23 @@ int nw_alloc_dir_handle( int dir_handle, /* source directory handle */ int driveletter, /* A .. Z normal */ int is_temphandle, /* temp handle = 1 */ /* special temp handle = 2 */ - int task) /* Prozess Task */ + int task, /* process task */ + int *eff_rights) { NW_PATH nwpath; struct stat stbuff; int inode=conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 1); - if (inode > -1) - inode = insert_new_dir(&nwpath, stbuff.st_dev, stbuff.st_ino, + if (inode > -1) { + uint8 unixname[257]; + xstrcpy(unixname, build_unix_name(&nwpath, 0)); + inode = insert_new_dir(&nwpath, stbuff.st_dev, stbuff.st_ino, driveletter, is_temphandle, task); - XDPRINTF((2,0,"Allocate %shandle:%s, Qhandle=%d, drive=%d, Task=%d, result=0x%x", + *eff_rights=tru_get_eff_rights(nwpath.volume, unixname, &stbuff); + } + XDPRINTF((4,0,"Allocate %shandle:%s, Qhandle=%d, drive=%d, Task=%d, result=0x%x", (is_temphandle) ? "Temp" : "Perm", conn_get_nwpath_name(&nwpath), dir_handle, driveletter, task, inode)); + return(inode); } @@ -2025,7 +2155,7 @@ int nw_open_dir_handle( int dir_handle, XDPRINTF((5,0,"NW_OPEN_DIR: completition = 0x%x; nwpath= %s", (int)completition, conn_get_nwpath_name(&nwpath) )); - completition = new_dir_handle(stbuff.st_dev, stbuff.st_ino, &nwpath); + completition = new_dir_handle(&stbuff, &nwpath); if (completition > -1) { struct stat stb; DIR_HANDLE *dh = &(dir_handles[completition-1]); @@ -2033,7 +2163,7 @@ int nw_open_dir_handle( int dir_handle, *volume = dh->volume; *dir_id = completition; *searchsequence = MAX_U16; - completition = (uint8)un_nw_rights(&stb); /* eff. rights */ + completition = tru_get_eff_rights(dh->volume, dh->unixname, &stb); } XDPRINTF((5,0,"NW_OPEN_DIR_2: completition = 0x%x", completition)); @@ -2047,7 +2177,7 @@ int nw_free_dir_handle(int dir_handle, int task) { if (dir_handle && --dir_handle < (int)used_dirs) { NW_DIR *d=&(dirs[dir_handle]); - XDPRINTF((2,0,"free dhandle:%d, task=%d, d->inode=0x%x, used_dirs=%d", + XDPRINTF((4,0,"free dhandle:%d, task=%d, d->inode=0x%x, used_dirs=%d", dir_handle+1, task, d->inode, used_dirs)); if (!d->inode #if 0 @@ -2092,7 +2222,7 @@ int nw_set_dir_handle(int targetdir, int dir_handle, return(inode); /* invalid PATH */ } -int nw_get_directory_path(int dir_handle, uint8 *name) +int nw_get_directory_path(int dir_handle, uint8 *name, int size_name) { int result = -0x9b; name[0] = '\0'; @@ -2100,9 +2230,11 @@ int nw_get_directory_path(int dir_handle, uint8 *name) && dirs[dir_handle].inode) { int volume = dirs[dir_handle].volume; if (volume > -1 && volume < used_nw_volumes){ - result=sprintf((char*)name, "%s:%s", nw_volumes[volume].sysname, dirs[dir_handle].path); - if (name[result-1] == '/') name[--result] = '\0'; - up_fn(name); + result = slprintf((char*)name, size_name-1, "%s:%s", nw_volumes[volume].sysname, dirs[dir_handle].path); + if (result > 0) { + if (name[result-1] == '/') name[--result] = '\0'; + up_fn(name); + } else result= -0x9c; /* wrong path */ } else result = -0x98; } XDPRINTF((5,0,"nw_get_directory_path:%s: Handle=%d, result=0x%x", name, dir_handle+1, result)); @@ -2128,14 +2260,15 @@ int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len, int modus) char unname[256]; struct stat stbuff; NW_PATH nwpath; - int completition = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, - (modus) ? 0 : 1); + int completition = conn_get_kpl_path(&nwpath, &stbuff, + dir_handle, data, len, 0); if (completition < 0) return(completition); - strcpy(unname, build_unix_name(&nwpath, 0)); + xstrcpy(unname, build_unix_name(&nwpath, 0)); if (s_stat(unname, &stbuff, NULL) || (!modus && !S_ISDIR(stbuff.st_mode)) ) { completition = -0x9c; - } else completition=un_nw_rights(&stbuff); /* eff. rights */ + } else + completition=tru_get_eff_rights(nwpath.volume, unname, &stbuff); return(completition); } @@ -2152,11 +2285,13 @@ int nw_creat_open_file(int dir_handle, uint8 *data, int len, struct stat stbuff; int completition = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 0); if (completition > -1) { - completition=file_creat_open(nwpath.volume, (uint8*)build_unix_name(&nwpath, 0), + char unixname[300]; + xstrcpy(unixname, build_unix_name(&nwpath, 0)); + completition=file_creat_open(nwpath.volume, (uint8*)unixname, &stbuff, attrib, access, creatmode, task); if (completition > -1) - get_file_attrib(info, &stbuff, &nwpath); + get_file_attrib(info, unixname, &stbuff, &nwpath); } return(completition); } @@ -2175,10 +2310,10 @@ static int s_nw_scan_dir_info(int dir_handle, if (rights > -1) { DIR_HANDLE *dh = &(dir_handles[dir_id-1]); struct stat stbuff; - uint16 dirsequenz = GET_BE16(subnr); - uint16 aktsequenz = 0; + uint16 dirsequence = GET_BE16(subnr); + uint16 aktsequence = 0; uint8 dirname[256]; - if (!dirsequenz) dirsequenz++; + if (!dirsequence) dirsequence++; if (dh->vol_options & VOL_OPTION_DOWNSHIFT) { down_fn(wild); @@ -2186,29 +2321,32 @@ static int s_nw_scan_dir_info(int dir_handle, up_fn(wild); } - strcpy((char*)dirname, (char*)wild); + xstrcpy(dirname, (char*)wild); XDPRINTF((5,0,"SCAN_DIR: rights = 0x%x, subnr = %d", (int)rights, (int)GET_BE16(subnr))); if (*dirname) { - + char unixname[300]; while ( get_dh_entry( dh, dirname, + sizeof(dirname), &searchsequence, 0x10, + unixname, + sizeof(unixname), &stbuff) ) { XDPRINTF((5,0,"SCAN_DIR: von %s, found %s:", dh->unixname, dirname)); - if (++aktsequenz == dirsequenz) { /* actual found */ - U16_TO_BE16(aktsequenz, subnr); + if (++aktsequence == dirsequence) { /* actual found */ + U16_TO_BE16(aktsequence, subnr); up_fn(dirname); strncpy((char*)subname, (char*)dirname, 16); U32_TO_BE32(get_file_owner(&stbuff), owner); un_date_2_nw(stbuff.st_mtime, subdatetime, 1); un_time_2_nw(stbuff.st_mtime, subdatetime+2, 1); - return(un_nw_rights(&stbuff)); + return(tru_get_inherited_mask(volume, unixname, &stbuff)); } - strcpy((char*)dirname, (char*)wild); + xstrcpy(dirname, (char*)wild); } /* while */ } else { *(dh->kpath) = '.'; @@ -2219,7 +2357,7 @@ static int s_nw_scan_dir_info(int dir_handle, U32_TO_BE32(get_file_owner(&stbuff), owner); un_date_2_nw(stbuff.st_mtime, subdatetime, 1); un_time_2_nw(stbuff.st_mtime, subdatetime+2, 1); - return(un_nw_rights(&stbuff)); + return(tru_get_inherited_mask(volume, dh->unixname, &stbuff)); } } /* return(-0x9c); NO MORE INFO */ @@ -2254,29 +2392,22 @@ int nw_scan_dir_info(int dir_handle, uint8 *data, int len, uint8 *subnr, + void get_dos_file_attrib(NW_DOS_FILE_INFO *f, struct stat *stb, int volume, - uint8 *path) + uint8 *path, + char *unixname) { uint8 spath[14]; uint32 nw_owner=get_file_owner(stb); - int voloptions=get_volume_options(volume); f->namlen=min(strlen((char*)path), 12); strmaxcpy(spath, path, 12); up_fn(spath); strncpy((char*)f->name, (char*)spath, f->namlen); - /* Attribute */ - /* 0x20 Archive Flag */ - /* 0x80 Sharable */ -#if NEW_ATTRIB_HANDLING - f->attributes[0] = (uint8) get_nw_attrib_dword(stb, voloptions); -#else - if (voloptions & VOL_OPTION_IS_PIPE) - f->attributes[0] = FILE_ATTR_SHARE; - else - f->attributes[0] = (uint8) un_nw_attrib(stb, 0, 0); -#endif + U32_TO_32(get_nw_attrib_dword(volume, unixname, stb), f->attributes); + U16_TO_16(tru_get_inherited_mask(volume, unixname, stb), + f->inherited_rights_mask); un_date_2_nw(stb->st_mtime, f->created.date, 0); un_time_2_nw(stb->st_mtime, f->created.time, 0); U32_TO_BE32(nw_owner, f->created.id); @@ -2289,22 +2420,22 @@ void get_dos_file_attrib(NW_DOS_FILE_INFO *f, U32_TO_32(stb->st_size, f->size); } + void get_dos_dir_attrib(NW_DOS_DIR_INFO *f, struct stat *stb, int volume, - uint8 *path) + uint8 *path, + char *unixname) { uint8 spath[14]; - int voloptions=get_volume_options(volume); f->namlen=min(strlen((char*)path), 12); strmaxcpy(spath, path, 12); up_fn(spath); strncpy((char*)f->name, (char*)spath, f->namlen); -#if NEW_ATTRIB_HANDLING - f->attributes[0] = (uint8) get_nw_attrib_dword(stb, voloptions); -#else - f->attributes[0] = (uint8) un_nw_attrib(stb, 0, 0); -#endif + U32_TO_32(get_nw_attrib_dword(volume, unixname, stb), + f->attributes); + U16_TO_16(tru_get_inherited_mask(volume, unixname, stb), + f->inherited_rights_mask); un_date_2_nw(stb->st_mtime, f->created.date,0); un_time_2_nw(stb->st_mtime, f->created.time,0); U32_TO_BE32(get_file_owner(stb), f->created.id); @@ -2328,12 +2459,15 @@ int nw_scan_a_directory(uint8 *rdata, nwpath.path, nwpath.fn, completition)); if (completition > -1) { int searchsequence = (searchbeg == MAX_U32) ? MAX_U16 : searchbeg; - if (get_dir_entry(&nwpath, + completition=get_dir_entry(&nwpath, &searchsequence, searchattrib, - &stbuff)){ + &stbuff); + if (!completition) { + char unixname[300]; NW_SCAN_DIR_INFO *scif = (NW_SCAN_DIR_INFO*)rdata; + xstrcpy(unixname, build_unix_name(&nwpath, 0)); memset(rdata, 0, sizeof(NW_SCAN_DIR_INFO)); U32_TO_BE32((uint32)searchsequence, scif->searchsequence); @@ -2343,14 +2477,15 @@ int nw_scan_a_directory(uint8 *rdata, if ( S_ISDIR(stbuff.st_mode)) { get_dos_dir_attrib(&(scif->u.d), &stbuff, - nwpath.volume, nwpath.fn); + nwpath.volume, nwpath.fn, unixname); } else { get_dos_file_attrib(&(scif->u.f), &stbuff, - nwpath.volume, nwpath.fn); + nwpath.volume, nwpath.fn, unixname); } return(sizeof(NW_SCAN_DIR_INFO)); - } else return(-0xff); /* not found */ - } else return(completition); /* wrong path */ + } + } + return(completition); /* wrong path */ } int nw_scan_a_root_dir(uint8 *rdata, @@ -2363,15 +2498,64 @@ int nw_scan_a_root_dir(uint8 *rdata, XDPRINTF((5,0,"nw_scan_a_root_directory_2 path:%s:, fn:%s:, completition:0x%x", nwpath.path, nwpath.fn, completition)); if (completition > -1) { - if (!s_stat(build_unix_name(&nwpath, 2), &stbuff, NULL)) { + char unixname[300]; + xstrcpy(unixname, build_unix_name(&nwpath, 2)); + if (!s_stat(unixname, &stbuff, NULL)) { NW_DOS_DIR_INFO *d=(NW_DOS_DIR_INFO*)rdata; memset(rdata, 0, sizeof(NW_DOS_DIR_INFO)); - get_dos_dir_attrib(d, &stbuff, nwpath.volume, nwpath.fn); + get_dos_dir_attrib(d, &stbuff, nwpath.volume, nwpath.fn, unixname); return(sizeof(NW_DOS_DIR_INFO)); } else return(-0xff); /* not found */ } else return(completition); /* wrong path */ } +int nw_set_a_directory_entry(int dirhandle, + uint8 *data, + int len, + int searchattrib, + uint32 searchbeg, + NW_SET_DIR_INFO *f) +{ + NW_PATH nwpath; + struct stat stbuff; + int completition = conn_get_kpl_path(&nwpath, &stbuff, dirhandle, data, len, 0); + XDPRINTF((5,0,"nw_set_a_directory_entry path:%s:, fn:%s:, completition:0x%x", + nwpath.path, nwpath.fn, completition)); + if (completition > -1) { + int searchsequence = MAX_U16; + /* (searchbeg == MAX_U32) ? MAX_U16 : searchbeg; */ + completition=get_dir_entry(&nwpath, + &searchsequence, + searchattrib, + &stbuff); + if (!completition) { + char unixname[300]; + uint32 change_mask=GET_32(f->change_bits); + xstrcpy(unixname,build_unix_name(&nwpath, 0)); + if (change_mask & 0x2) { + completition=set_nw_attrib_dword(nwpath.volume, unixname, &stbuff, + GET_32(f->u.f.attributes)); + } + if (S_ISDIR(stbuff.st_mode)) { + if (change_mask & 0x1000) { + int result=tru_set_inherited_mask(nwpath.volume, unixname, + &stbuff, GET_16(f->u.d.inherited_rights_mask)); + if (result) + completition=result; + } + } else { + if (change_mask & 0x1000) { + int result=tru_set_inherited_mask(nwpath.volume, unixname, + &stbuff, GET_16(f->u.f.inherited_rights_mask)); + if (result) + completition=result; + } + } + } + } + return(completition); +} + static int my_match(uint8 *s, uint8 *p) { int len=0; @@ -2415,7 +2599,12 @@ static int get_match(uint8 *unixname, uint8 *p) *(p1-4) = '.'; } #endif - if (NULL != (d=opendir(unixname))) { + + seteuid(0); + d=opendir(unixname); + reseteuid(); + + if (NULL != d) { struct dirent *dirbuff; XDPRINTF((10, 0, "opendir OK unixname='%s' pp='%s'", unixname, pp)); *p = '/'; @@ -2437,7 +2626,7 @@ static int get_match(uint8 *unixname, uint8 *p) } closedir(d); } else { - XDPRINTF((2, 0, "DOS get_match opendir failed unixname='%s'", unixname)); + XDPRINTF((3, 0, "DOS get_match opendir failed unixname='%s'", unixname)); *p='/'; } return(0); @@ -2452,23 +2641,159 @@ void mangle_dos_name(NW_VOL *vol, uint8 *unixname, uint8 *pp) } -int nw_add_trustee(int dir_handle, uint8 *data, int len, +int nw_add_trustee(int dir_handle, uint8 *data, int len, uint32 id, int trustee, int extended) /* extended 0=add trustee to dir, 1= add ext trustee to dirs and files */ { char unname[256]; struct stat stbuff; NW_PATH nwpath; - int completition = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, - (extended) ? 0 : 1); - if (completition < 0) return(completition); - strcpy(unname, build_unix_name(&nwpath, 0)); + int result = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 0); + if (result < 0) return(result); + xstrcpy(unname, build_unix_name(&nwpath, 0)); if (s_stat(unname, &stbuff, NULL) || (!extended && !S_ISDIR(stbuff.st_mode)) ) { - completition = -0x9c; + result = -0x9c; } else { - completition=set_nw_trustee(stbuff.st_dev, stbuff.st_ino, - id, trustee); + NW_OIC nwoic; + nwoic.id = id; + nwoic.trustee = trustee; + result=tru_add_trustee_set(nwpath.volume, unname, + &stbuff, + 1, &nwoic); + } + return(result); +} + +int nw_del_trustee(int dir_handle, uint8 *data, int len, + uint32 id, int extended) +/* extended 0=del trustee from dir, 1= del ext trustee from dirs and files */ +{ + char unname[256]; + struct stat stbuff; + NW_PATH nwpath; + int result = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 0); + if (result < 0) return(result); + xstrcpy(unname, build_unix_name(&nwpath, 0)); + if (s_stat(unname, &stbuff, NULL) || + (!extended && !S_ISDIR(stbuff.st_mode)) ) { + result = -0x9c; + } else { + result=tru_del_trustee(nwpath.volume, unname, &stbuff, id); + } + return(result); +} + +int nw_set_dir_info(int dir_handle, uint8 *data, int len, + uint32 owner_id, int max_rights, + uint8 *creationdate, uint8 *creationtime) +{ + char unname[256]; + struct stat stbuff; + NW_PATH nwpath; + int result = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len,0); + if (result < 0) return(result); + xstrcpy(unname, build_unix_name(&nwpath, 0)); + if (s_stat(unname, &stbuff, NULL) || !S_ISDIR(stbuff.st_mode)) { + result = -0x9c; + } else { + result=nw_utime_node(nwpath.volume, unname, &stbuff, + nw_2_un_time(creationdate, creationtime)); + if (!result) + result=tru_set_inherited_mask(nwpath.volume, unname, + &stbuff, max_rights); + } + return(result); +} + +int nw_scan_user_trustee(int volume, int *sequence, uint32 id, + int *access_mask, uint8 *path) +{ + uint8 volname[100]; + int result = nw_get_volume_name(volume, volname, sizeof(volname)); + if (result > 0) { + if (*sequence==-1 || *sequence==0xffff) + *sequence=0; + result=get_volume_user_trustee(volume, id, 0, sequence, + access_mask, path); + } + return(result); +} + +int nw_scan_for_trustee( int dir_handle, + int sequence, + uint8 *path, + int len, + int max_entries, + uint32 *ids, + int *trustees, + int extended) +{ + char unname[256]; + struct stat stbuff; + NW_PATH nwpath; + int result = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, path, len, + (extended) ? 0 : 1); + if (result < 0) return(result); + xstrcpy(unname, build_unix_name(&nwpath, 0)); + if (s_stat(unname, &stbuff, NULL) || + (!extended && !S_ISDIR(stbuff.st_mode)) ) { + result = -0x9c; + } else { + result=tru_get_trustee_set(nwpath.volume, unname, + &stbuff, + sequence, + max_entries, ids, trustees); + } + return(result); +} + + +/* quick and dirty hack for 0.99.pl18, 25-Sep-99 */ +int nw_log_file(int lock_flag, + int timeout, + int dir_handle, + int len, + char *data) + +/* + * lock_flag + * -1 = remove lock + * -2 = remove lock + log + * 0 = log + * 1 = lock exclusive + * 3 = shared lock +*/ + +{ + NW_PATH nwpath; + struct stat stbuff; + int completition = conn_get_kpl_path(&nwpath, &stbuff, dir_handle, data, len, 0); + if (completition > -1) { + char unixname[300]; + xstrcpy(unixname, build_unix_name(&nwpath, 0)); + seteuid(0); + completition = stat(unixname, &stbuff); + reseteuid(); + if (!completition) { + if (lock_flag < 0) { /* remove lock */ + if (lock_flag != -1) + completition = + share_set_file_add_rm(lock_flag, stbuff.st_dev, stbuff.st_ino); + if (!completition) + completition = share_file(stbuff.st_dev, stbuff.st_ino, + 0x300, 0) ? -0xff : 0; + } else if (lock_flag == 0 || lock_flag == 1 || lock_flag == 3) { + completition = + share_set_file_add_rm(lock_flag, stbuff.st_dev, stbuff.st_ino); + if ((!completition) && lock_flag) + /* add lock */ + completition = share_file(stbuff.st_dev, stbuff.st_ino, + lock_flag << 8, 1) ? -0xfe : 0; + } else + completition = -0xfb; + } else + completition = -0xff; /* not exist, errorcode TODO ! */ } return(completition); } diff --git a/connect.h b/connect.h index 1d9e6e6..f37510b 100644 --- a/connect.h +++ b/connect.h @@ -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); @@ -153,7 +145,7 @@ extern int nw_find_dir_handle( int dir_handle, int len); /* L„nge Pfad */ extern int xinsert_new_dir(int volume, uint8 *path, - int dev, int inode, + int dev, int inode, int drive, int is_temp, int task); extern int nw_alloc_dir_handle( @@ -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,13 +175,13 @@ 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); -extern int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len, +extern int nw_get_eff_dir_rights(int dir_handle, uint8 *data, int len, int modus); extern int nw_scan_dir_info(int dir_handle, uint8 *data, int len, @@ -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); +extern int conn_get_full_path(int dirhandle, uint8 *data, int len, + 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 void set_nw_user(int gid, int uid, - uint32 obj_id, uint8 *objname, - int homepathlen, uint8 *homepath); +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 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,24 +242,48 @@ 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); -extern int nw_add_trustee(int dir_handle, uint8 *data, int len, +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 diff --git a/dbmtool.c b/dbmtool.c index 8c851f2..76a1ddc 100644 --- a/dbmtool.c +++ b/dbmtool.c @@ -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])) - return(do_import_dbm(argv[2])); - else return(1); + 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); } diff --git a/debmask.h b/debmask.h index 47ba9b0..89db75d 100644 --- a/debmask.h +++ b/debmask.h @@ -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 */ diff --git a/doc/BUGS.nl b/doc/BUGS.nl new file mode 100644 index 0000000..6db4deb --- /dev/null +++ b/doc/BUGS.nl @@ -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 diff --git a/doc/CHANGES b/doc/CHANGES index 19c9a8a..aaff720 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -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 ^^^^^^^^ @@ -393,10 +395,10 @@ Erste 'oeffentliche' Version - Verzeichnisse werden nicht mehr auf readonly gesetzt. <----- ^^^^^^^^^^ pl4 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - negotiate Buffersize von < 512 wird nun ignoriert. ( Hayo Schmidt ) -- namspace.c: +- namspace.c: - get_dbe_data_from_disk: Rechteproblem beim readlink beseitigt. - max_dir_base_entries nun auch in conf file aenderbar (section 63) - - nw_search_file_dir so abgeaendert dass das Loeschen von Verzeichnissen + - nw_search_file_dir so abgeaendert dass das Loeschen von Verzeichnissen nun funktionieren sollte. Evtl. muss bei sehr grossen Verzeichnissen max_dir_search_handles(section 80 in nwserv.conf) hochgesetzt werden. <----- ^^^^^^^^^^ pl5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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 + 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 +<----- ^^^^^^^^^^ 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 +- 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 +- better file share/lockings, with code from + Ingmar Thiemann 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/CREDITS b/doc/CREDITS index 1993a48..7967528 100644 --- a/doc/CREDITS +++ b/doc/CREDITS @@ -16,6 +16,9 @@ Guntram Blohm Uwe Bonnes many testings+notes +Valeri Bourak + added some code + Arne de Bruijn testings, exploring ncp mysterius (netx), notes @@ -26,17 +29,26 @@ Csoma Csaba testings+bugfixes Przemyslaw Czerpak - testings+bugfixes + testings+bugfixes+more bugfixes (pcz:) Ales Dryak his linware gave the kick Fritz Elfert - gives bugreport and patches + give bugreport and patches + +Przemyslaw Frasunek + hints for possible security bugs Peter Gerhard testings, bugreport, patches. +Georg + fixed bug with print queue handling. + +Sascha Herrmann + docs, scripts + Victor Khimenko cyrillic filename patches @@ -61,9 +73,21 @@ James B. MacLean Louis Zammit Mangion testings+bugfixes +Mendel Mobach + some doku + +Norbert Nemec + some patches + Matt Paley adding QUOTA support, login time restrictions +Boris Popov + ported mars_nwe to FreeBSD + +Paolo Prandini + added login control routines + Jiri A. Randus testing bindery code @@ -76,8 +100,13 @@ Mr. Charlie Root (alexey) Andrew Sapozhnikov 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 + 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 testings and errorreports +Neal Stephenson + patch for glibc6 + Morio Taneda testings, bugfixes Erik Thiele testings and doc -Winfried Truemper : +Ingmar Thiemann + added patches for better file locking/sharing + +Winfried Truemper re-wrote `INSTALL' and added explanations to `nw.ini' - +Jukka Ukkonen + small patches diff --git a/doc/FAQS b/doc/FAQS index 9373afa..9e99560 100644 --- a/doc/FAQS +++ b/doc/FAQS @@ -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 diff --git a/doc/FILESHARING b/doc/FILESHARING new file mode 100644 index 0000000..06709c5 --- /dev/null +++ b/doc/FILESHARING @@ -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 +--------------------------------------------- + + + diff --git a/doc/HOWTO.ger b/doc/HOWTO.ger index f821997..670aea5 100644 --- a/doc/HOWTO.ger +++ b/doc/HOWTO.ger @@ -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 diff --git a/doc/INSTALL b/doc/INSTALL index 754e483..617bd1a 100644 --- a/doc/INSTALL +++ b/doc/INSTALL @@ -132,5 +132,5 @@ the mars_nwe-package. good luck :-) -Martin Stover +Martin Stover diff --git a/doc/INSTALL.nl b/doc/INSTALL.nl new file mode 100644 index 0000000..52010f2 --- /dev/null +++ b/doc/INSTALL.nl @@ -0,0 +1,133 @@ +INSTALLATIE: ( Mendel Mobach ) +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 diff --git a/doc/NEWS b/doc/NEWS index 0bf5cf6..431886b 100644 --- a/doc/NEWS +++ b/doc/NEWS @@ -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. + 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. diff --git a/doc/PIPE-FS b/doc/PIPE-FS index 95d3d34..fe953fa 100644 --- a/doc/PIPE-FS +++ b/doc/PIPE-FS @@ -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 diff --git a/doc/PIPE-FS.ger b/doc/PIPE-FS.ger index f78ee14..3b52647 100644 --- a/doc/PIPE-FS.ger +++ b/doc/PIPE-FS.ger @@ -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. @@ -29,7 +36,7 @@ case "$1" in # save directory /u3/mar ;; *) - ;; + ;; esac Unter DOS kann nun diese 'Pipe Datei' mit dem Copy Befehl in eine @@ -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 ) + +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=) { + 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 + diff --git a/doc/README b/doc/README index 4874954..6dc80f0 100644 --- a/doc/README +++ b/doc/README @@ -68,7 +68,7 @@ nwbind: Have luck with trying. :) -Martin Stover +Martin Stover BTW: The kick to make mars_nwe public was the publication of linware ( lwared ), the NetWare-Emulator from diff --git a/doc/README.FREEBSD b/doc/README.FREEBSD new file mode 100644 index 0000000..e8e8195 --- /dev/null +++ b/doc/README.FREEBSD @@ -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. + diff --git a/doc/README.ger b/doc/README.ger index 6428d18..2b52e53 100644 --- a/doc/README.ger +++ b/doc/README.ger @@ -68,7 +68,7 @@ der fehlenden bzw. fehlerhaften NCP-Calls wuerde ich mich freuen. Martin - + PS: Den Anstoss, mars_nwe zu veroeffentlichen, gab die Veroeffentlichung von linware ( lwared ), dem Novell-Server-Emulator diff --git a/doc/TRUSTEES b/doc/TRUSTEES new file mode 100644 index 0000000..9e6ae05 --- /dev/null +++ b/doc/TRUSTEES @@ -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. + + + + + diff --git a/doc/VRAGEN.NL b/doc/VRAGEN.NL new file mode 100644 index 0000000..10c466a --- /dev/null +++ b/doc/VRAGEN.NL @@ -0,0 +1,30 @@ +Een aantal vragen en antwoorden. ( Mendel Mobach ) + +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. + diff --git a/doc/mars_nwe.lsm b/doc/mars_nwe.lsm index 5fbd637..9047b75 100644 --- a/doc/mars_nwe.lsm +++ b/doc/mars_nwe.lsm @@ -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 diff --git a/emutli.c b/emutli.c index e3cb0f0..daf9e98 100644 --- a/emutli.c +++ b/emutli.c @@ -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 -#include -#include +#include "net.h" #include #include #include -#include -#include -#include "net.h" -#include -#include -#include -#include -#include +#include +#include +#include + #include #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) { - 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))) + + /* mst:04-Apr-00, patch from (Jukka Ukkonen) */ + time_out.tv_sec = timeout / 1000; + 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)); diff --git a/emutli.h b/emutli.h index 663de33..6752810 100644 --- a/emutli.h +++ b/emutli.h @@ -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 +#ifdef FREEBSD +# include +# 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 +# include +# ifdef _GNU_SOURCE_ +# include +# else +# include +# endif +#endif typedef unsigned char uint8; typedef unsigned short int uint16; diff --git a/emutli1.c b/emutli1.c index 2a0d135..947d6e6 100644 --- a/emutli1.c +++ b/emutli1.c @@ -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 #include #include -#include +#if 0 +# include +#endif #include "net.h" -#include -#include -#include -#include -#include +#if 0 +# include +# include +# include +#else +# include +# include +# include +#endif #include static int have_ipx_started=0; @@ -154,7 +160,10 @@ static void del_special_net(int special, char *devname, int frame) if (frame < 0) continue; sipx->sipx_type = frame; if (flags & 1) { /* primary */ - strcpy(id.ifr_name, name); + 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) { + + 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; 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++; - del_primary_net(); - add_primary_net(devname, frame, network); + if (!ipx_inuse(0)) { + del_primary_net(); + add_primary_net(devname, frame, network); + } } else { if (!wildmask) return(add_device_net(devname, frame, network)); diff --git a/emutli1.h b/emutli1.h index 9600099..5aeb22c 100644 --- a/emutli1.h +++ b/emutli1.h @@ -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); diff --git a/examples/comm.c b/examples/comm.c index 7f580e3..0bd01e4 100644 --- a/examples/comm.c +++ b/examples/comm.c @@ -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" +# define DEFAULT_COMM "p:/unxcomm" +# endif #endif #include @@ -19,6 +35,8 @@ #include #ifndef LINUX # include +#else +# define O_BINARY 0 #endif #include @@ -28,32 +46,172 @@ static int usage(char *progname) return(1); } +#ifdef WIN32 +#include +#include +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 **pp=argv+1; + int size; + 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); + } + } +#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++; } - b=0; - write(fdout, &b, 1); - close(fdout); - while (0 < (size = read(fdin, buf, sizeof(buf)))) { - write(1, buf, size); + 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); } - close(fdin); - return(0); + + 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); + + 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); + } + + loc_close(fdin); + return(0); + } + loc_close(fdin); } else fprintf(stderr, "Cannot open PIPECOMMAND '%s'\n", unxcomm); } diff --git a/examples/comm.exe b/examples/comm.exe index 0d074a54caa0e583d402f2c0bc04b5548550c584..cf3c53b9644a15666d5004785fa6069470a74b94 100644 GIT binary patch delta 7926 zcmb7}4O~;#`Nz+_2{$i*f?z_fD*_70sXRC#T{@P+yGs`0lo%T!RO#I_zSoI{scY%&7cXq3mU;u znWa|oCK89iE1&@!1P8!A@GEdJfRJ~C2r=`7^o$|oIyej#g2^BN+z2J43tR`Egb>mM zUIGmqoKV6+(2R5wco*D^CFBD5oduT{fcX25@r29+?J=6<#)DD7AIw=#h#n+?1aO{h0tr_>A@{&PfD?QLz676v_rMWQ5B7sS z;2E$1tOSd}JTL{sfDqshR6quliZ*V5YvY`t1-uWAgS}v@1(%gzCWr)AywD2p4tNo4 z0ds&B1Oo-=m$z|O!D+AytN}~GY+wLm0Rb0fZCnF500gid%mWdC2O40RriKFeLWPRK zeh>$IK)14u+Xr@oa*zWSfOL=y0zofY_Z_$b-UqutB`5_sARLSW1|QS|9Nul*o1h#N zdAF%JJrY`AKO%ojW^a;z#jq!8DXUx_S*xgN)d>b0x7|h9rGE%>L z%4_#9$6NFl$_O5UO;S-}Q+y4#fqk!AdAv#$`{(}ee_vrZNY5(AG6(5(Wwa$KD)HOJ zQ2Q`$i6nUXL*;u8rQ?0#N-hSQKoNKX6cSs67``Cg5Ge^~WuJB^VcPLmvNHGFIic(5 z+?_`G`S25u5`H1XG9#9THOh#n@ykfQkvw!h+{!N{RorsYD3@;R)hdBueo04p@6+}- zm#c-|$xX*yu3NA7UgWEqYA!dIbKf_F30X?P$kA84CtD7&c(VgZZ-;O}xZF}1$hf@x z7@^HtIhOfZ>ac@s@#TYo%s#QkzmpvACNsBPH-d5f&`4NQ4+cG3;?>9yC!5%0!k>w6 z^kYQX#$grBJ_n=SimwkU>h3F!lN4Fv^naikDQQ}0p-*VQU%hf%#sR@NkjlXY=gM5+ z8|v#D9Q+Y0wC$|C!0r<+IEVGNrD_(+E!SJQkLWbtN0>vj!gm65$o{4;&-hJ}Ron|I zm38cv$=c&xFE6lP8P>Vsb?HIsJt;S$k{cA$nuP zx4s8itFf;tcc9hS@5j*2fV7|FBnK8TO8UFN$!tci{jy`2L5Wq8#1v6tB^83=nQnR_C{Ed}RF|l?8M^6r zLC^5r%9=B}=jAmczTg*CJ@ zI0R<7QE~p=%A*+5E6z!M$TvnZbmpi7Q2yJfoy=zX#OP=#9ZX*v-4>O{5%civP26(6O*{B$UVX0@8=< z--miJEFMMQm=zcxOZc_Shx8O56Y>$umT<1*k67nQ!Pr+{PI`>qjG1*lQ}-u36DDU= z&64ReFg;8=5vm65TwDchau^=IT6*|1x;kDbg3%{^8cT|Ogj`P6-cwmmuWI8^{jl)$ zA$YmiWwH16isRSQbdS^_x;s3=8|8jWoN|+6fsCg5ZA7FT>Cmya&4^J zwf<0;i<#YO?Boc72jBQVl5_ng+f7WOaIV_euR%6^hG3_EBTGc*QSOUr1;f@=dPQ_- zwiF&-j|yQ9&<~?xWhkZmv{7`x%=;^`qVggJQnvbuCpP{ZGbv5im9yt2(v44+LoHI4x66myav++r!tipM`{2bT+fhYV(>;-W)LY=Fl zgO^Y~)8tqt7B8FTa+L(fTSYgmuvpV(g$Gs*i%EiEkK)|A-3^K(pc&P!J%)6fjR zuQ?Uw&B5`)uw9Zmy%@cLp)@TfR9(%(OD)>Jhpvk;_)}hVE;C+8{xzS4>t1>^=I0|Q zKg@9tK}Eh)tSvs3-$i4_m#L{}?ALsJ{a*Tq@i{Q)6&u4Gr4wVPF-PqiVh=OEUSHHFZ!z)-aefv3bBlD#LOQOh)R_+*G9v9_vjFXW(;aUmez%g1K7Z%aT zY0c6^6e{qIoD@B!DbBk0meN{zL+Rog>7V05W;Akx<*wQr$_fKsV{-?_P<6YDKOv6p zyY0BV&|XoFf}o0WB{3^q{Atd`pTY2#qii#ci_d0S=r7|}Gd=Y0@g_|dw~OlrH#j^? zht8UOi?bST(|HqL55*mSotq(Rm$eJGg|1j<@ipNaYrKQ2(sa_Ggs^cAod9vca2uiM z2I%JMu5N{gh1~Sl`~V&_$cbs3VJnRqS8kpMo8QQO^WryD&`9@Hpm5yTv5l0661Y8 z?9XZC9x;DOr>!*(4v z$Q{58nWYwtO6y*tu%ZCZj5X`G8SX(}(-dRCu+&zwgw6{@hR(ony zIh6>Jrp6iLO^|nPf(4~nD`l;W5d$Wk_nE$mW=_hQe=){{A?=(4F>iC?HbWmOGB$ci z6%kGDoOV7Xp^U)Ley{J`Z&fp8j5mrpd|2ZG@YK5<|Q?W?ns*D?vhHeOVG5P zm7xmyWzx^t?Q!&oTtnk?xsl&vYbJ(#DT3Wu~hN!GIvA`W@_oP4~Gw*G-+sGi2DX{0HhJ>ugZd3fkU{iU`HMFitbXV#~MoWK}8a85m zlKA|(hgUR@cF(_V=XNFzRoF*4{S?V?x_*KTPSTC~)t=TU2K++DKDnHmhyheXDN=9-W2atZE8YldTM6sUC(!YsyTH>>Px9dQ_rMcO#LR6 z9)08~_NKueV+>#tu1xEi);G<^z#C!=lMHEw`G)0&LPMFM)AQY7c){>n!(qb-!ygS7 z3||=N6B%>awlsPo<8gjtT3Oomw5qiIX?1C*(mqIgHO(&likw#bG<%3a#4ilClhEQ1-fLskErs_Jr0Q$kFf>*(fu9sBt@TAQCH-d)XqkJTNbbp@*x&#O$s8e7)cRfX*`Zl`$j7VX?HW7Ggn zF-o>VAm`s zqL!E=CwDxHy4}bp3?qu*qreeFn`enPJYTfNka79{osCD`HY}1WnI0pL|CdH~4RK_z z$Hp7TBjggU*Ie`A_Mlr|NI7EJclXPPcZ9p$ckdT^?vdYX2$Not>=*}k#)o{+fF-rBajM1 z>SnK)HVFxfixaZ7N7sg zQ1M|f<-+s+j)=wRD2v!rGn;eo=v-jNGN2Q%1hS~S`< zpEJMX?gN5b(Y}z?nb;nCp`x8Ebi3m!y={BWJzm6Qr5fj+IfX?0X4_)1FT_B~Cv2g| zd)rs&U1yl9w8yPp$P8*1LgvRhZi)ND(Q54RZnFF_TdafRBsMvdJV|G;Q{x^qeEu!M z&lu8`;>m!!7jV|qkIjJ-hXMa99tKo&d4m66^K8aEtbU}^4Xl#n#AGv3oO1-Fh}oBM z5K*CEbQRew9{M%g+j(?W$%KH~e z^9hYNhcPL1zFC+0Z>qY2s!+eQop7%sN_UeVtQqBIFs^1Sx^k?W3p|WA&!{QuF^KC`TttW7I!U^hyS>S z9dvuyXht-q@tHb+;3m~<`~TZLCE6V*oA?vE4OG9yW0!8&;w?Gq|1XZxItZEQyIUR! z|5S@!5|7BN*>asVgT<18)p=*g%|6nBg6$1D_UVQ0j@|v_=n?ma;ip47K8T)t+IPzN zFtNXTjB2LD*S$Tp{l`b3buVN(#74NDjtaJY8##j`%h|?pQw4>9Ipatte~+1&grZfO0-ouw92vKv*iA-&cLSN-wr8{W5eAw z=YsIV#7QFjv2vK3N{1 z&KZ7tEt&So%mW_p4YK41Kx9{2`I&Web1*AWGEkDWJ@@(F$qdL}WB#+b*Vx+P6(j zE+`^1Ru>g*EYWV<1(}*1T$Q;?B5}*IKNg&dycsO!^&y|R$eYfJi~R?mRgC?Jd;&vl zzqn;tg#U>y2PL2eyabMbv)~eNfIbl9RjY^vDPTTW29|@z!5&Zt-T+PDBKQjY1N4Ai za0lE4ec&GG2S0e#rYi=JZ~o3t0A@ z5c=C48kG=*h%Q1;?I_@0#?Jac9GV)8L+R(sCd>_4AbknjgFa%kYVl;#uQO7*>cne6 Kw3xpR`Tqo;itd5{ delta 7586 zcmb7}3tSUdzQ@l@!b!qYd;~-s9%^_RR1{kSfvOEHwQYO_@qyY_6hyR0P^%JZtZp1j zbx+s2RI8M|-EQAYtT&}wq`*qo>aMkWEf*~7Wm^{uRoAxaA~N?k6F}k#zH>hx^yuPF@*o+*m6H)fl1A?jN_RZMy-p{C2;c{9k=N-}&;pvk zdtehN1ZEHo8q|c`24QNaMh}LAK;R1~;6b0tsp$bXz;$p1d;>0l4$ux-RZfTIJZ{c` zKY~->BxnG2pcWhlHQ*ia26zp;3SI$~-~jkJr~rGwF0ccXfoDJ|C+zfiHbf32+=#g3aJz2QCpH1W<5WT}S@{J^~eBCCC8}fiw^W zBvl4qrnag0S|{UumyX9^X*P)F zr|7d1;Wuhe5Z>Uz({I(EU(GaK-RQF~u=5Vv;X6)%V7-!+TyLzP>-ZBM?FTkp!k>D- zd&6liV2!@fTmie}8|&CGA^F>dP#a}jqzKl%s6A1m?fjTXDaBv|C<29`fK(b0z^stI zI$jaBW!KecVY>4?S)Tjpr(*Z9IeRSXGf}mV5Mds~UKzJI!lNRx#@X?LhfF&Yuz@sFerz^L`@7on@l~4zkvOI7cCm{xg!?yeys-TTbq7Cz4Mq5nElmyU7ElzyiLw zvbD<@nXx>9d9lM7rZ4y!8hClJF%y9*%VJ$@NzJSp`q4Qg~vJv&sMHb+2Od zfa0}5#lI_xJn3@W)x4r;eisPM<++Uu#cpReZ_94B^g+yDD(!;{Su{to^of=}6NP78 z%X7uAmwgIJTlO)Fm`laSv}dAfZ{kb!JumEKWmB&vZlIU6N;iu?RRclh_h!=nW{FMxbz2kv31YxO8%gD zwkz;vt4SZOc3f(v2YE?y>C1>ml2B>`PZXD>Qg!ElGXJ0iu8`dql*kpjR|N^&u-m-z zc1Wq}@;;TS%_#l)kedzb;rQ=)_Y1=txCOUp2c4+-mM+n((Y&U4TT`RaYuYp)Xg<<> ztTAajwW9V-ZKCfQ<*U^MYA$~raQSVWQl4m|COw)>=b^;f8QaqpETWRly9?QWjQlpB zfOlDX_U86ATY6gwJ2EQ$o|LXpMcjP0SU-jT{D!+izmMbAv53%D9pUQj5l(X%A=^Sl zp^W^N|NO7wOSvj>_fnP1*5|VHc4@sSl$sk9domH~-)MPj-vv7BX$HgX=ee)L4GN9$YSTW65($_ScD!@c0*IH)^H<}&#;H1^PN0Y};>X$fuB}xE+{Yu;oNlmNv&N_-sD2kU2iJ_~6cn>5dMpa~Mf5~m z8>3evJz?BvTpt`a4n^jV`-+R2Lc3J8)9D935=2c zWWBRVTU9_^7I_G#Wr-~n4F;!%GdQz(0vWwE&=V}klC~IUQ`q33c6O^V#Pmh9s*s{9 z1)(pAHZ3}l3u)DbY?fi__(Cd`Qdv`-EKMi_hFkmMJP z3{W7P%r%ec7v zF9>@DHQ6grA_rPqHi~Q)(7Jx-N`l~0t6=x({B2*CsxwGZ%9DeoRWW=!E^JD>V4c@l zqH;E=7g>|r_FTYh*!B5EMR2~gbBUa>Bu$b^LX9rjNteErWyVLL1ms2y=H53Uh}c7o zVqmLRWLNyUn0BEg*JlKAo+HH%+-$fe*-fzB`FV$Lhf-g-7m1q-EG)qs+%Cvo%{PiE z7X=%x9V|cL$>HrnVCQXw2K8c(8uc{^t*kv^vv0dx#znzc-N9BQ=5Xz-HZhJXV_zkv zab@o4iEnWM``dGJnU=HQqzR64sv>z} zM+ruFIYlYxKze2JIze;LH`)wSaLH_QmLVs^DJyCv z;b&A5_F`nHk(bCilCrsdY{sOOTs=E9$*Mn2U%;yG1zJn-){|pgDZisGa~B$kZlVe1Pi)JkAQfh&RR=r273rN*5T3tk{ zYA`N|WH?T3*%h>uBufz4OyEV$ttDcMrn(+uw}B;1nUvB%tBXlhJ+0nA8m;r^&ZB}Y zd*Me|M13jG`|76L;g}+xDA62}1hcMdzNkM>tNu(`S8_Z%F~vuFUJ0p4I6Wm{*r1lE z|0AtBtw;r&>dk4Ue^kVfVov^%*g0Bt)+@G17CWbiA?3ZF7E96&N<>dh2pUq}DO&Xj zTRL@8@F~T_C%8%}vvpF+Om=u`0)LURQ&Xcyp2W)uZlndf4B4a$Ne^y6Ty_lUTxY zkoL3q+I{;A)pco=FkBIDg?!frSkT%dm83V~aihC{<#nl!v@6 zf?8mQm)o~z_a(|+OnH(!&7#B*7BroXGGh-(h+19?IlB$s7;JOLPd~>6chi(+8b-eD z+uKr2G}V2S1>9ej`93z5@<;wvlODI zpUu6`LS{TY{3a|74bihFBSdfS56|2;?2aiaXxrqWlf)kOgvp}PkUI9JX>Pwn=9Hll z3)#ffEJfm()cwk25STV*at$`T@}~qF+zx4|{I+Cx**oPPFW0igX%WL~rpj;P3f9v7 zv!d6f|4JTe;IHh%wCPGgKcpop1&=qc9GGH`m??LMy=IQ@pO!|mZgV&{(ydD`^Wk>7 ze>Qt3$1Pw1mfjUPsjE_pQXQ!;rXEiHDD`yeYpKVS-$&ED-?r4hrGA&{lNOQ|oi;Ho zE$z=UF3q?#!{0RClx&)5vYFPJwwgrKE2i10-fxYm-t?KN(f>PG5^y1YxDc&M)S0E@AotFm*&gnn`WQ%Vd-PiW7ApG z!*lov8EpN-YlYhM#`M$aU!;GP-kq+^7?JUPdY|$uH}CD4>@&5VUocDlk$YKGT85mC z(;uQD3;XYt)_cg?N!Ga^&H8}jWAA6$IZOG@6Yjh@zACPqJ^lDtzV3JKeUC5XxYh1U z)^!|L?p`pjjN`Xv4H(yt#)-pV7e)ZXK=^QSmYXg(uHsvdx$Cm69A{=hIWzg&HEe#) z7y3hUn{s|{C@uVh36N_EUTBd_1>c$?dA#Q|NwSS{wjUa7PP9d8qRCx09NU>-ZV zcGL*$!w|hJy)Z7Xg91G;y0vX8xe_Xtfsg!15;d^hNU!T@?~t}h9$nG zSbE8FqgS(*4Yni!rz>Z1dLk!%fZyGbz5QWe3(jNO`@?`FQ6(Ha$Cf?)E5}1P_~?*0 zf3H?EHu!2HYso2Ua;sne1*8*>lMUlD4?3;=))udkt#PDy&A(^kfY*jYapjeMBgg+u zBdtRm>FBr7gET?}90+wtkHYN%w_=qPId8^bp5ze8ry-?8C7;TK4I(Pd^D%6D-BcsIcaBQrXDXmyC5toI`c_Dk)H7XO13I`LJ_$1K6K7eEeDfCZPH#SH;LE6L{r0JD! zsbm{!>)j+<<)3`zG_BKeLtVgOz5Rn#Npr}FkJ}qzgA7fVlWmpfpp?@!LMpwke}32X z+tvbZz|Igm=4v%TKO{j!=|{9=j7y}+a0O2qmry9kdbfyKz5iT<-v7Qn^moM{)aw6Tnl>MmI_jY_ncF=M^GWPM)o%A(b)2$5C);vB`k zb2>O1+qm;S*0D44NutBa$k0zK9(?(M`P!Rv1wTChV?kMD7LR#l$VZQ~nY_Fvy!(mg z+@GlvIks=tb%%g|2pWJHECQ>+R`5JH3~E3V_#f~CQ2RJFpX^V zHaG$5!N;HhG=e7ZdvFpo`#3W+pWx;X;0w?RdO;wLt%ATX5DbQc5nv=31@s^Ugi@#b zfuGIgqj*dZkK0Qk*XKp9TeWU|@s|F|o}WO70(0-l_qmRL{r$}yCGO`EUm9~r`4avN b+KY=^i2opxVbdUvYm9u&jg`~iL;C*$+u=Mw diff --git a/examples/comm32.exe b/examples/comm32.exe new file mode 100644 index 0000000000000000000000000000000000000000..da1a5ca71ef263953deb9404974f3c0b05a19d44 GIT binary patch literal 35328 zcmeHveSA|z*8fd%+g{p~1W2Jmg`nZFTES{S(X^UETZ#gvElu&^O%{r!i*0T11>A?1 z)SIkL#wh;QeQ`hgVi)&WT-|-#pSp{?z9bE_fNy}SqUkqBPpqHQGyWt+wCUw5D!G zc6O#CiP}>p2n!6N@WijLx;E9?QNd!!GNcJY6>=()xf2ju5t`}Qt*4E8zbS|M&p!w7 zoqQm=I3U%d$~+#7C{qw3f>6X0|Gi&lffxT@`3{=-CxVcU;71tt zaes5yhe3`c|EF`H?O2gP5Nf>aX~zO2oW}!wwHE)2AS;w!v`n@aT_xxFwi<4b$A?QD zdG!T=@o4`j7X)>;6qX%%fj*1>K|m9Xa`jp^I=t9nUK?ECuo8S#c!9&_sq8Lw4T(ipDGNg7hH^AYX*Z?)5%#KVMHkG-l|m(k5`RSLEqImn z$ad!E9S%g~9CnZmM0<=Uf64Z%@0(6O+Et3RVuIA))u?2EhYxb7d8Z1r(#LG|GsndlM;~ZO0xNB?#3u z-rD*nd~QL@L({BR-7Nh@J$q8Zs-ZwLXFZ z6=r8bJ)gN{x|*b?X!?Tmc-+x~+Er^4$Ub{1v*?3_N1dz}$JlI%3V2xNY^ z)NF?^*e3CsN-5oi2dLNIPrwL+f5G)Sb)8DUow!_ISFu+!kx+d8LSG9A!4wb^0o zGTPN{an8aZ(#l?jzA_AOvKw7Sq2NGrjOSEU)@X+cc~5J!$6S;UlWjf=ngwShtPfwk zU<3=QPd=`FaF)c5#(KI3D4$06JPiizJ{?OEF$ahI{5}P|?e*$Jj)=MAjI3O-d}-Tm znk}(pUVNOlzA(iSjW$3ufbpVP!Hgb_wncPoSVhcF%wJFa(}T70^jf=!n=~gA)1F3a zFAsjIy^wZutyf!3Gj0LoeYeO4FmZA{m0oR;K3mvfZ>{z>0AP?=Y~_ljsoA}Kdx!6N zx8TKcm9dLh5zkZyY+EvS+0fh$Dryit+Fo=NHFwnihSmsWMuXU3>rSIm0@EJ5u-MWt zQTtDz>L76R#(C)310W}!#xsIus~WYdonqT5kLngS|I-=y<53i|y{tESDoy=p3Nwdq ze*zii6Y8miEC%)|>D@-G8VR-2?ruBnZbPkuD^e6_u5p6!$lk}?f*-3_&-3U@s)#R& z>M=W5>Huf*vHnO10+@59*MkWlRaRm3%9{fs5ZlniHZ70X*o!JQj8z3y*)*EQqzl)3@fmQ{=P5LgA?-Jur;j>yX) zzqY_}xrUvC`2c0Td^4tU$VB4a7hzy9n|mqav6ws)Mq?jLe3F_JoDHA!_n?)Y_JVuLk6F z5D#}ejW18fPWooqk0Pqn?mWe3X|U`=k9HRT<5OALF=l0%!G%XXmD+FhF^RD{jg=ks zXpK5{bd3avE$m$r%%)Ca3b4N~CqYq*Hv_RzPSZY}j3LHId$jy1yifJSfkY08DSDWc zDw=LmEi1Qrvy8c@Kpo6$r`kVmZC{FoWJ ziie5M`;ZSl$9re4*MS9FOj-fm=Um8}fh^=%+ zFe``xOlNr}Eeind+ijJLz1lCq2t0uf--jO)K73HOo3vx0yIi7ZMGTeAtis&4$10D~ z`HKpJQ;myw+pz^kT_3>qz6MF>KId_$LwTVo^ZZBJmpR-)J>TNb2UheVKQ7TXW?&KU z=Q$6#IxY8^QRX{i-#pHDX4AIOmKS0nUvCrmeAE&*IwO`B{81}JHaZ}x0~wfvMV5P? z&%j_f0xwT>3)tvO5oRLfBRCMOn83L-#zQ;i%|2dtKR@4=&UU#MNY#0?bT zV?cqPSk0u7SbNr>ls_8yV@>MO$REp7k3Rl*UFwlm5^GOB9(`x7P_Dt|QV(WSX+>Du z!8DZSLomV_1W($)ezE^B^^*#EPJr!}7hVdBzYi}iIe_f^o_CRjL~hR;ND#`)!+ws^ zqxFDSI?7x^`7{7h)b{)e59oZZ<%QS7W?#7U<^yOTw`V)DIRpNn4$QFJ+lEJCz?C`! zauIQgsW;Z1)hPAdbgg3dZ8OYNCQ^yoZS=kDOO7N5x)DI=Us1=-03U!WL6y7hZ!|^v zN<9Xjd?_}z+ra`Xk9lYsN~Lx?h!0J{YBev3>B}I+00BVHduho*u=CaqBp-b*>wJ#j znbY&UIxx#}?+>x95j~IS^eju#^H?D`rDP;4^@9#8GUV$A2j@NBn&`m}aJxq{(1h3Z zo-H%59V`P^XVQcPowgn)+Q6<)qgtu0)ho7_I+i_85CqMkvI#0RP;MOxv+o90fsIRc z($M#HN%DBhi}{!&Hnc$J1mWQEp4Uwv>BW4?L54u3Juf1U6)#aS5ok*wJx5oFdU_tE zB2aW8jmXJ;0aCwB9Z1MV);rkYXE0pYQu#I}67I)1D{jDUn#r=4p#{ohZ!QWPO7)3F zW$RjXwjgJ!5hE|bQ6zeBfN4FKp>e$?^=+^wYGnIRL2~QhCkvtgK21W9V###$BZQV9 zzkN}=oU<0oKwgT^YlBkH%YX)#2J?c}o@bE-kWyllFJ>nmV!)O`FlL{p>rCOS!Q=x<>rS~0sx?BnZF&+(N+351szF&knf#EG`qmmw8O z*25Mc?DWaAz~0$irH)GqeNj4yI>0@leSzcB_@oph;Q?fp-ZQ?gL2v082j>S4VW4xjrL$MFUXx2fcHzTJtE#E>V$kcg zQxmz!En$Z#ON|w38u#W}}J?lA7C|ODdo({x}}2;U{<-1)95W4>8du zkM+$iRK&n>WmH8OWpoLJs5uj>bYL`%FfkdlUeVWWkTYnErpL$k#ggfQcxGSBC}&f? zod%8z?q=+i*wPA47o6*hnXwu_t*@%sIX&Lm2D?UNs=KZ6jARKx)0$i9g|uCPRrfnO zKwk{YPG3w^#^|NB4Tahiy$F50lC+i|fN_E2mizBV457D$mnYV;bO?2Yr%LTIYDb|a zK*Pn6=n^)xxMO8UON%|)m?XBBZo%5nr4uX4xfg&^j~@eJ=y6hC_>!Iwc()&_8R*l` zL8M-gB4R^7@~XTwo>cvKhi8&o`13_>;S|ERCc1?u5S~Fejj$hOvk;de{2RgqgldG) zRJS0cr5V!nk1@@ZmL_gziOT^0I6^MM9}zg5_>CU}N{vGhrtKQ){o!IgyqxD2B9q<1 zYQ(3J|6`;(QAY6w#AgxjLU(B3L4BvavB>oY-z;W2RwF3Uh*E;{5PZ>Cqm=I*GBwKA~hl zn9V^0*Y*+@o|d+6udczl#Oh^x76u}{vzVpl$QkR%>BWqtmft(}t75URfB} zx9uPN#F6aMh4n8-T|4ULk$72NNUyE-lxy<|N5+LXK1ksp0+^&m#h?TufcxwPhdH#7 zDwj}RGQcXo2#_l0_1AtGfqJZh8?(rSqfNniBWcXSVPul_$w@k0h~e*2X>b-DLtVYy zX}ABzE!e@&r!rgZT~NNe(?LO^eMK6}CJ?ntYKu}0*NK*+kXjqI1V_{@tW`HV$_0y` z>_g~Q1x>k+C@qCI;rJ_HS;jJD4PR;5OpCjfG5}`g;?m5uAC24Ft_P(}GUe?+2VFzKQbxiFNUD3@u<4^=B zi~2y#I{Pru=d*`m4cJ)Nc=#UcIs{E%KF1Z~l< z7!6t4D@4LlK2O~vx_USNflbdtE$0!I!vV#2!ZY6?>02B)0v@)(-q43`q7$)-{=<_Z zYUFcI;te*SCKB=$wL?vEK@Q%i4j7e;P`PM!$8*&IlQN#tQrxU(rBUQ-FBj*kXH1*J zoKkG&x#$4NmAboPP>eA6To(UJ1|!ZNt=%{#(6>QSyDaKQz45dcXj5eu=TpxQp?KpQ z*Q^hJH6Sm%&IMz_b*zF0_Cp9u%KXwTJ_%F;$6Jnpd1@)^#%VFN zf^;m=duB`=sJHqcZ4$n;bVxH+i+YiA1j_jgIFLh&2JFkQ9BbF`9P=P19b>ZG;L*l@ zWqHQ|oO$^ofhEM?RYun&a%O_v7_LG@sBXi0frCzW+RK1MKZN#+$-JZ7$g&qxU-!wE zuvs3Y)Q?5XxEz)awn&KsdNI#zjo0T<&u!H68}y#nJ1ECaIr(}{;D|D&raO%~M9m~} zu0#jOc#`4`#mV#jW{1_)-)iA)fmJkx`ddzbkGveZV3t>lap&+czY5rB&lB!EY&=eW$SZh$KjpyW+*oC~fHakK|4tOeZIXSS;^CG@OrEMNEp(^s+>Hv_`N zi4!YzRwtXwNi~K*g2~@`+?n9Z!ouMaNEU*qDqp3ZF(_j^+G%bi=aQIL7QYBw&FPC8 zWf(|~4wfj!tbrj3L`Aj-#}&xo7r0IP51*f${6_1}do2D;kiOGx2^bMOk6=~G*=Yrd z7XJzKn=O(Y=Yyj;ac1N?J~11)eFZtnzv(6!SxTB?vTL-zT9N~!jPh#R^*PjEZszP= z&)Lfsl8!C_ImLX_nwpy5~FC+aE#fM$*$ySV{*^cf* za5#TxO7K;XKbh?-QMO_^O1Yq-6gF!GyLtAp$1#7%s>!l@k@Qq~s49%um0CKdG!KC3 zyRhnRgK6ZvKHjibl8q8vH`QVut!C3_V;0a1=YI(gA_ErY-awyxqgOi)^BERttX~QF zDn=Jf0<_W;6c9{o5Nfp_P65J&iAVJvFY;5|UK}Il}zH#_gPf3=*GbA9h zj;hGX`4HcxH(j4@$qkz~6ucQWhntbpP3QzQYQ91{QF2nqhTKVFlV%bnW+#($+%`}7;XBu!> z`9WBGhE^1h_IehWjVm=#zZeY8A`>pOs!`g*|KwT~n@)&BHG=;T#7sAO>*wLO=lV_; z%VpKt1HeHPV@2mRS0-zwfFUeax=zD|Xg`}hbS0`r#FLNW0A^*qp~V*qrnvu*^3x7# z&Z99%EO2(G(Ib6ynPu*<`oA0UAx^bo-(kmtHhdnw6P!0N_xr*bk-S4Tw zwG0+;+V!YzMQ|1wyI1ZYTQ}|+B=nC+PU+OR)~tm>?Fbz2CX)a(J#?FInSY`&kVgd- z!4$_GUaoKUC5ksxVQ~9ST_Vr+?~`Zh_I&@tJ->!*SlEO)7^VqwdPr&?UG7djriHBS zv>~Y(Ynfe%R$v=*KAEsZq*v z{(Xw6A}(P`5xdG0P_=L_cfgWl@tZ&qU4Po;G=em_<0p829Q5I`WQan{d3(YT%60DZ zozZP_N@i$@!Cit!xsN(KtuJa&U}iv@n+%r_Dx>o_Ha3Uz5LT9lI;qWrJ?!oIxQrQ7 z!uyiGtej1mJ3lx@=?zKf?Q-aDnbeuZ=!|?TI#33V7-=Xzh84wud>1eC~d_sm71-lR~@EI4xImhdqQT6#Xiu8Ed1y35c6 zA6`3zl}SrWf)I#~qi7NWG2H_x^*Z}VQz%}HG^Wh7#9Mrw&fu$Ld<>TD!?cLfdb-O9 zTsx>T)GkZlhj@b4V%BR|{G{HkRd2){mpm5cKe7WV{i(#q1zioo!2x#z%%vpsHD3Bo z1D zF5Rp7O|lNb_VA|hHMAF{_9OL}4V|y`Xzzh>OzWVH75H5mrdGa^sUydHjXC>VA1fA( zY{bJd5A7OI-NN&#Ld`+5C><`lk*U4&p8A1oO70c3sAR- zUqtlvvqU`MO7kut7$Q5lyA#B4lEQgapvswuejtV)m%xTlnZP~=X@#Lh2GDi+AYJJo zYfR{ez2Kd+oroivJ`a@}VTuAx2XL^I)P&gb0+z&l&kjxlwrYW~v#7$pCjdDoCah8h zNDF2Y4a_a+WUO4VgXo|Er(V)%>-tA`8c{?ab>KWy4gLt?gv2xn!lVwIyD-ztGtVlP zj@hU;1WqW?IWcV+xd#l4-FO*YQam@4-#YC?v}+93>DVq&qVKVKn!cTpSQy3MLwFeB z=Lo+<5MXQ~qtoEWXxd&ooVmo=$V$!%PWcX^cLxm_r)t8upq}hlKsX8Z_=QAvcEVw5fR-&et~s!J5P@#gszEV=sbgHT=|8xve6VFU0*g`3IixiwI2ET2-ZE2?n zKMU{NYYLalEi44xP!)*uvuwGUl}Y_>PNXG3+Fr11fR$N;WoN@>1HrjxS*w}-heQ;t zg2JV4en1rDGH*@z+t$S52gKzofFUa)J2w>ps#<$YKPI8nTdlpzA0$+3FtE}GByAOT z3MM`foNGp12^CPpWT0=C_K9I%b9pl}0 zY$pa|mk{83BTkJjNzQ`psjQf;Q(8{A%*UzB68JH|QVm-Ci|~X-vy+Wl{Kd#LK}m}8PX?zx%QWjCe!?)CHxbfPx_^Ls%XRX zp)#&=HkjDk;rkrKLbb=-}*a z)=ycdKm9Fx>DHvH5*1*Jskhn9$_i(u1W zm9K^-Rq=h3=j5Z>)!dQ z+I(dd_Fox5!w_MjCqLYBMUxud6=WRKwbE2+(muisX)~cuq`iP{2+&cYy!?gWUL#)LG_ac)M$$d3oDE$N2kEEh}pPXQK+<2RFAp`+a!4OjLy&b#Jqiq zjqWI=wQZ*o!p72eNna^gPA~cc?uj^E)2iPf@N1CV27{;G4tn_28;DJ+MSKtd4Qo|) zcUn8<*cHTyA-~EL2Vw8QOPeWo`XjY z{`27BtbNL7{U>p2wg$eA{Gzx2Bh$f_(JsJklv*-efZbqN&t z7klpr!yAX!S|yox%us!clLsjXmRIZJ5&=U73@WJVp{8+_brUuW%*PeCVRVuM4r}x# z8gM$h(Wk?#i#%P|iIuR-@s%oFA2ker$ANpvx&b?Bt&;J41P}3x`3_faw__WmjgAC} zX}AdUllLzx-i+r4v0gxVy&%v~57&~Z1QP)z2Em(ni;ViOVQAaV5pE^FgCYo2CeDsX zQRvvMXI<8vMk&gQPl9$&36@P+!G$>GQ-alq!7Fh6fL6l`bHm^N5ikeKY(d2u#MV?} zhMsr=S+GsRujQwmH>*+U(zkAQ2P+4Hcb_d5pi6B2;8|3LUdGPDCS7Jtqkg)2Tl1go zMa3r*VXp+ER&ad#cL(syYOHNtL=LVA2=3FC_qbvl;~urJ?Id#6gBv<=vaT9n?+4Rp z5LT{mMz|A|J{0_$+e4GJ$=azSxPI2rUx7QL7@E$eWZQY7UbZu@$kK662pZXFq=S`W zO8wxY9D{ilaM%K2MCJHNF=xfZD|MR{p1qHN3g_|gAFOsk_><6klhAe}5vt5%^Q`s6 z2@_}mfys_Q!lvujH!Q~n$+ah#jl**7N^?k$FN3id6d1y zw&9o|&rrXUn^5w(kcDrytJf!#EH}nNAAw#TDWj^iPxPJL#rrFBypWd%=71bpY>6Tg z+g-#9SA}&$nybRrlEs8#&YT zktD0_6zAT=4q}d59kB191U3?@c8^ZX&{E4=z;a0ANfu)>hK64zl~^&|EdBuSvAd=4 zW4U%D`U_5|ALmBTo1!0?O}(yjtut7LE4F#k^((~<OoS`M*w61&?PzAM-DIjW}fsw;TaTI~;mRZDo)6(Zfqb<@bXK1bD29n?qHUh18E zUC&Zdsi+CwbvB{k_27iy-4YE6R+^!L@hBJ{yenD27Y}UC*Dti<=Ch1CI)>euoEsMZ zQBWKI0Qn4x<^YUQxdrE#RsAG4nlMHGVK$w|Vez1XebKrli+LodN9C@Aaxd#@5Ti%U zx{TJMnmv(23y`bZ5_pLi2%j*Fq1CxB(8u;~y#{{tVUO4?&@cr(XS;lKa!+&{=()Ru zk6{{@*r>Efd4p<)1H}K}be#pQqam$w287kMx8*a}-bs;5qrozB`${Y?63Z-jDVWLT zi3RX-ogxL{vu_FCOM<2IM*Hn)*d`+KELLG{zYVsmi=-WdHaO;w)PBM1x?Kdbn0a!+ zJWp=8ZKyVI;OLcFxKr{8G3Ij`nid*n7FQ=m$;M8Ee@+Wj%MD?1O#2vDtkue{L%HeG zg3jP|=vdqwu9dpyVZ{S&6T;%Qu;^n4!X;Als94a+XO}4o(-HTI634q@5YXIKC6tb% zWD#EG5W?jK?ogs+z-9!vQ?C83*TWEFbA7Ii3f@W{D6hmXDtO!Vj^!RKj&yTsW4-YV zZi+YchOZnSzL$FF(pr8Uzc?(8*E@`!jw;w6%m9Y?-QioMpe6q8aFfJ7cb#b68aAgY z?QOk_cjeNr>&j$mxn;qy7I7A`wLGsMxMN@0-l*VJNsfRY?c>8XU$}f2KXm@57KRl6 zvHm3Oi?x_v?2UrApuXirPn*FoJN)Dq9L$AZ@B|D>F8kDVa>JzdDa=rCGAV1OuAqT0 zgPh~7&0(`E{C&=r{To+@Z8y3Owwir6z;-&vb+Cmdz#>#H6I=ruXS()oC=3TU?B3Rk zf(wPv7-s~A+fkv#5)3_u~c5yVQ+`e-~p)9`2`2DtpUg81MpsiBP?p>6?}?y%K--(ndG@D7AvEcOu4ZvV1+>Xi+Zy zGFM4}lEiwn1jGU3n>1x5vw7oV`bx)(@Ne^N5hi|tNBSU9@IE@O{o{6Y1tbP`r^z)N`{;Br5 zq7aNQ8vL?g7drkdtIP27!BO zd_ib2L!M7!q3MQtrqF^yXe5QA@BMS_7#_-8xncU&JaUvlJ{bcbDj%@nf(Y5ocp&5m`p0P#7+;u>+_P94saLdC+InV-N}4 zeBK8_Fng3mcuh{m`8*Yo%Ktiq#@wAo;Dj%J1qwImFgzldob5?*gbIbpO0Y!t_UnI1k{za zm3Z^RlX#sZOWmCt;}-m0nt#h2r8rn0A#p&Mt)#Py>2QkUl@v%=0%y<}SHF_YjsJtS z6NatXgKIX&cb;-g08YU`3T>6JrIV$a)}~ZGsJaCfYMZh3Lio@E$3)EBi7@C+4tWe% zyeEXPpy%H3Qj2)Q{tfFw6-HbpzC}2VN^9vaX94-5fffK9S-}GKH+OR*jEZl2aWr=u^Kvs7I|@h zj+zjLZ=nlr3`r3otgO-z(zW>fuy`%*KR-_4nGN7sDPXS$ph*mNAe@bYQW{t!uJacEcElmCfn`69 zX-GS><)H{JL+D!96;(!iv=T14;tt9I>o$TO+9xNaUV0j<{ro+yE-pzfsJF#%c9QfB z=C)XasQvsnCoGA<;=dS8c0&$eCETSWy%wvw)bZV&0sx!QDK zpqp2s_+!hNKJ=L=b3qIue1A1?@ z|J|_p8C)x1&(I!&`I0ygkq-omp6o7tk}r+C>pi7>lNcsHus`ve`daSVRE2Jn{}p_T zs4(&*4RC!3{*#M$rzn2L*=i&;62S7bDMhjr6$WkL$5K^`KZLZNqkODa zU5|oWl+#OBpn|kA7MuX?&6oe{kBRf=x3YA+cH5h9cEX3WOMFZ)7~14_v8rF`?~^C@ zcjCk;$YzRh|I-zm5YL5$0yhIljn>@&kiv_f9H%ofU&gW;%pm;A06MG$Qhj{+#`EO{`I1g|*hzYf(Fh8(r*tbRbRr2h`{Q*|@`3@+kTbQ(x)z&|kKBwUhd4 zL=KU2)bj>7-kmop6M_C6y?`BttJ|x3+7**0!(UH-fI=f;%xUr0wJCNOO8614WzV0?hVYw(0nwRx^Yo{E}=BRzq(xQwzr)k2jI=mCojWwPvcCD4+oG|uwp9L z-HQS4iU!4JsL>$LZ@u()nZq28D_~;hrD%K5>-fFsM``S1{#ymQUnNF9X`ko%Y3s%> z>!yQ;7PaV_gyMx?r|KqE$EKb#C`GC!$TKSB2^GrK)pWh_2*!?O1oH}MD3->m8$SPv zyuL5xeX|xiG+Jo(j~EES|BhTtmX_Jq=TP^RsnqYW6?mav84m^G zvv?-HKaZ0y?O^A+#X>C4*iiKK;a`%dq5i?4Yw{N_I~H`(X)i2x$|fejn3_`SFVMR$ zSdXDkh`}5>sW|uTg5Ra!vdU!`(URhN#)bg)N@BSP6!-_2lpO}`uE;=7QFy2K+%Q`!+8XymV3#!3;L{;Zs#hi zYPAqeHf$oegrJkC#eWbrT+`{kskIsHlLlsk&&VfYEtEIy2;Yful$6sUgL(0VwVFiR zP;#R$cSb_#usON*v>4eQtXg>xkb^9_&4U{Ln;p2W<5*#i!!KOaQx9avmDGnLmOv2g zbE~&*S?AXgw3Sr-U!cwgYM_me)e+WmTm7RnMSxMcB;|*GQH>V+C^^k70s5JX6tAHr z#^{tmzGw8|&M(!0h?kEI@x~0M^r6dup(7rdp|Mu4wfx?=7ED_El$d&XJn3vUIdrpO z4h{w-{6#U{i6wee%8I&r5U`iu#Lf>YV3pd;55V&Sq&ggurwuECYQ`^RS$Fah zmtVyWZO~|LX>10I=>IH&F)4LO)$A}xAlcQ@kkRd zBg$lbDWRG}3j)~Jwwvn3a3~~`27V)lrk^k7=9l?Zcuzd9tJHDv4fvWo17B01g*}0e z#pzW~n}`WJ~lkxUpJfqMzz+YjQrqHx0#kSTp~( z5B|CPYsn-;Bw{Vgle1_=1O9Q=cs2@%N%W&cpC@pr3 zV^Q^}sh~@qTp^FCump}nzd=nKDn{aClPNcU`;_v0=wG24=~V{`E%%ZFG3hAV#>%5yU2;*+Jpg!~6#IBhu>h!T zIkLH!j4iUeXDyX+1lJb}X(+SF4t}j>3EV4g1xfG@~d{H+KT4r+sMK`B#_6j37uTC0O5l~95ur%8IZU>shMf<&3%3`-9Z zBySvk9Ok>|ZD^Te5_{G6k^#E(sWi;MNzkVOH7V&C5!P*jp}knxp;-IguV^owAi}#h z-xByQ5VzB3@&Agr28)!@;{OSf4aSCqR}0d12nS3vsg_gPib;7;Q7UhS|Ho%KQQX^- zI*Msf2%iZrq_RlR8Zl(3hzWCrZ?mItqH<}CS9=?E(Fd|b+Pqp^e`kYU9u< zwW&kx`4SW;%g0^McffhSdkj@Z=KrrV$r zAbba*4Phz-oP6?ze=hLPL&2~YL^+u0g4JRB_FW3$J5`%6&PV5q6qCXfPww=m3jTMm|etHnQtii{{a%U#Wh zEf)V-(1JBG5BS-M0+^~S_Xm*mEZN&}vxD`HU(}y`yjm;6gaXgmK-+n`J={fKTa2uW zUiHm|Eg--ZFaFl2M3}bb#@|r+NT-pj15E(Z1aUIKOQHi9RVZM&KnSU?*6Q^>>8Fgg z-Nb>|mYZNitJW6kMb+BO&$*yrYTQm!L+k(Rq~ra6T}UF8GlXBC0NjetF^~QV%sMm~ zuQ8}Jl*tzLf#6(MkD2Mh+E%0U{9@{FO#NUAm>&JWlsaS1^^PoZ}k!~v{e)Vkyh8@%W&LLB!Ip)#I^m#ToOUyCg zMH8lfh8LK`P^n3z=}Y?ocZk0!QxVPZ%5t1(hnJzlVbWN?YY#4faxLoT;9Mx9Xrjgc z22w@YaBoj9pV#vQ9v0%-eiD8qBvZ-4FNAcZXZCy_xn1emD8COWT1(-K0cE?U5^uS} z%GqG3Vz#WRd4u#NuerD-b_w7~vG#zOHfHEUFDv9+nz%*iUweA|2B2o6%G*n`(&AT< zFQ{V1GLfIDq@nFNUH;e`3=N4YEgj;CdNaYBqD;J0fF9w{kn1{Ux#wz}s0vV(eXPqL zv5)%6uv}*0KoVY-C4w2ocGDN3Ql|{_Hy!T@-S8<6)Pw$K-qzc{=0LW%Q^fBQ$PRNT zI?V^hVb&p1(tPi4i)Z1%jfWiHJ|Dd!*q%8}h$Iqe1hFD{hD)wesmJ6EA-QH$7Sq(l z5J)XH_=F%moxTDFp5J<`U@zMpFtGPw=5&jm7~1~-`$Grn_b0f8J_PzeVMwQq-71*U zg><7;EGsMHKMgReQ1B3dJ%6@mNrog`S6EoA3X~BLZhGv>+yFvRT1(VmG$e9#LvUZ>+Y&0dCfP}n??1S zm6kgDhIK8nvTD73t}*RSUdP`_q=E&i2Fjdh#W$ycqyug0#E?J|)#*srUv zr+PzlH#OG*aZ_V!6Zo*EZo|6O!(fvYV+iJ-LBwK%Vtv1a}H6o&ua*q-AaM0j*qdN31-x%!Vfa~bo@_ms`O zb>YI2MWy!3rnO#1^K{x8`<%Pwx>h@vmQ|4XjTo>yQpFe4Z(i42m#Vm~Q4p3bo7TFF zGFz7^jhj|C-FYXLlN+uYOxG-0Ld^*^#E~0DP1ApB+P<`TRm-Z@<#`Frr z;0KHR7e7#IXsP?!50z6G`HXPjU*$maWx9{U=4Q9B9)b2(0iuZmcO)x`1TULMaKzxB z9}G)}k>;BzN?_6%Og}Izy?t2v!C`57eL7W_Ub;@DO~8d+nz|s63TiOY+f{<_C<<=B z=k9x^(gQyKNteO+bo^3}+kSqOjz@xftB=P!0UzD*&JMd?{H1RwW&Gn##?SnV@Fhw3 z-vj=&UwrtBiNfE1q5Wd%*W=&X!E024p_T8fc*icRe5c`^YrYKs`r&tvo)Uzsw_q$>#6Lnz%zX$kEWCmr@gui>b@<-_w?F|@ zeCaPAnw9?d<+3m5RDh;$`t#%G;J^5HA$*%K^k)$MwZGvQ?h%Imj96j+mA_PdJ2)`% z8R7tW!c#b$47A?Rrxze6hQLNrBODmvzz7FMI55J25e|%SV1xrB92nui2nR+uFv5Wm z4vcVMgaacS7~#MO2SzwB!hsPEjBsFt10x(5;lKz7MmR9Sfe{Y;59R>*1{@vcjpO*o+ke!@@+{&pf?xb7tDQQ$d|~BK>jimlfMkbIKF>`)dk|Bds$_n3GOk5T_-{j?w$~#No;wlj z2+auOgVTaQeI+^w-iJVaZcE1ZAf|E^fy(^|gy%to%MpH-eC|L@{d*LF+WQp(!TkY& z`u8dVmA{2R<+)%A@#p{5Pf=v3XCFod;Vhm%8}#&*_#OWBkf19 z0{#+&LWDU8RS35uv>|!3!VCmALKVV#gslkoBm4~E354AU^!YSN&;RuPUoFgqm#th^ zzHWV8iSVYO3J%(orkOi;eN$^)#j3_Nc)X>oYEjvOl;`lj3AKyrWcV4+ZE9?U6FA(^ zOYrK7r;0lk|C&6I=fd?CRTr#l1l|P(c%Ao0X=#BccPg{dSi5db-Q4#fh`3FLIOI=;rkWYEF+yc+=))L`y!yw+pO{vC&AASvdt?)kK z|1u)sgRjoVqP2t5;h+DUoEu{2%&ZpA4R=K6=ZoJn8L8am^J&!|oEKIhKsRBIS7ysKK)(fbM|!g!*N z2C-z#nid*xVY^`geD9NP^}u#H)g2~FcX0};>hw+@$mfWVfm1Zq(|f{BpcY l;#novC&%_Z$}4SwV?BvsiD1=xwdU5fM3BA?jC>2i{{eFRJ}>|P literal 0 HcmV?d00001 diff --git a/examples/config.h b/examples/config.h index 016ac7e..33e64ce 100644 --- a/examples/config.h +++ b/examples/config.h @@ -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 */ diff --git a/examples/e.pck b/examples/e.pck new file mode 100644 index 0000000000000000000000000000000000000000..7259255fab3404c3427980ec6455dc87dbd7c492 GIT binary patch literal 447 zcmYc-$YkEm$iTqFSfjx}B;XNc0O|k&Fe#pErJtKvR2-jIo~oZ(k(gVMlUl5wn@zlN Xj8NmiW-5V6yu^RJvcq4J3laJN1>Ow> literal 0 HcmV?d00001 diff --git a/examples/mk b/examples/mk new file mode 100755 index 0000000..088f013 --- /dev/null +++ b/examples/mk @@ -0,0 +1 @@ +make unxcomm && mv unxcomm /u3/pipes/. diff --git a/examples/mk.li b/examples/mk.li index 395bcc0..0be7419 100755 --- a/examples/mk.li +++ b/examples/mk.li @@ -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 diff --git a/examples/nw.ini b/examples/nw.ini index 2e9fbd7..2567302 100644 --- a/examples/nw.ini +++ b/examples/nw.ini @@ -2,15 +2,18 @@ # This is the configuration-file for "mars_nwe", a free netware-emulator # for Linux. # -# last changed: 08-Feb-98 -# -# !! section 5 : deleting of ipx devices/routes changed in 0.99.pl6 !! -# !! section 4 : automatic creation of ipx-interfaces changed in 0.98.pl9 !! +# 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 !! # # since version 0.98.pl11: # the most important options in config.h can now be altered in # this file begin at section 60. -# +# # Most configuration errors depend on section 4. # !! Please read section 4 very carefully. !! # @@ -52,7 +55,7 @@ # /var/local/nwe/SYS -------> SYS -------------> W: # # More than one entry is allowed in this section. -# The maximum number of volumes must be specified in `config.h' +# The maximum number of volumes must be specified in `config.h' # or in section 61 in this file. # # Please note that at least the volume "SYS" must be defined and it must @@ -76,9 +79,9 @@ # # If the netadmin wants to map the homedirectories with the MAP-Command to # every user, he can do it in two variants: -# We suppose that the user test2 is logged in MARS_NWE. He has files +# We suppose that the user test2 is logged in MARS_NWE. He has files # earlier stored in his homedirectory /home/test2. -# In case of entry 1 in /etc/nwserv.conf (naturally amongst other entries) +# In case of entry 1 in /etc/nwserv.conf (naturally amongst other entries) # there are other results of the MAP-command. # # Variant 1 Variant 2 @@ -86,26 +89,29 @@ #DOS-Command MAP H:=MARS\HOMEDIR: MAP H:=MARS\HOMEDIR: # #Entry in /etc/nwserv.conf -# 1 HOMEDIR ~ k 1 HOMEDIR /home k +# 1 HOMEDIR ~ k 1 HOMEDIR /home k # #Result of DIR *.* All files stored in All homedirs of the # /home/test2 will shown. users will shown. # Showing his own files -# it is a command like +# it is a command like # CD test2 and then # dir *.* necessary. # # 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,30 +120,41 @@ # 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) +# O (uppercase o) # + OS/2 namespace (useful for Win95 clients, see doc/FAQS). # N + NFS namespace (not really tested). # # # 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 # ========================================================================= @@ -260,7 +277,7 @@ # routers, the shortest path can be determined by summing up # all ticks for every route and compare the results. # (1 tick = 1/18th second), default=1 -# Note: If ticks > 6 then the internal router handles +# Note: If ticks > 6 then the internal router handles # RIP/SAP specially. (RIP/SAP filtering) # # !! NOTE !! @@ -286,7 +303,7 @@ # 4 0x0 ippp0 AUTO 7 # auto ippp0 (isdn ppp) interface. # 4 0x0 ppp0 AUTO 7 # auto detection of ppp0 interface. - + 4 0x22 eth0 ethernet_ii 1 4 0x0 * AUTO 1 @@ -295,20 +312,26 @@ # Flags # 0x1 do not remove by nwserv/nwrouted added routes and ipx-devices # 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). +# If this flag is not set then all by nwserv/nwrouted added +# ipx-devices/routes will be deleted when +# 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. @@ -329,7 +352,7 @@ # SERVER_VERSION: the version-number reported to DOS-clients # 0 Version 2.15 (was default till version 0.98.pl7) # 1 Version 3.11 (is default now) -# 2 Version 3.12 +# 2 Version 3.12 # # If you want to use longfilenamesupport and/or namespace routines # you should set this section to '1' or '2' @@ -400,7 +423,7 @@ # # 0x8 ignore station/time restrictions for supervisor. # -# 0x10 allows deleting a file even if the file is opened by +# 0x10 allows deleting a file even if the file is opened by # other process. # ( this was standard before mars_nwe-0.99.pl0 ) # @@ -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 # ========================================================================= @@ -633,7 +691,7 @@ # It must exist before printing. # (_not_ the spooling-directories of the Linux-lpd) # NOTE ! -# A '-' sign as QUEUE_DIR has special meaning of +# A '-' sign as QUEUE_DIR has special meaning of # 'standard' queuedir name. ( SYS:\SYSTEM\queueid.QDR ) # # PRINT_COMMAND: command used for serving the print-jobs under Linux @@ -644,13 +702,16 @@ # command as last parameters. # NOTE ! # If a print command is not specified the job can/must be -# printed by any print server. +# printed by any print server. # (e.g. pserver (ncpfs utils) or external printserver) # # Examples: # 21 LASER - lpr -Plaser -# 21 OCTOPUSS +# 21 OCTOPUSS +# 21 FAXPRINT - /usr/bin/psfaxprn /var/spool/fax/faxqueue # ------------------------------------------------------------------------- +21 LP - lpr - +21 LP_PS # ========================================================================= @@ -659,9 +720,16 @@ # 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 PS1 OCTOPUSS + +22 PS_NWE LP_PS 1 # ========================================================================= @@ -675,22 +743,31 @@ # 30 0x2000 0x2000 +# ========================================================================= +# Section 31: not used yet +# ========================================================================= +# Flags not used yet +# + 31 0x0 + # ========================================================================= # Section 40ff: Some pathes (optional) # # ------------------------------------------------------------------------- # 40 = path for vol/dev/inode->path cache, needed for client-32,namespace -40 /var/spool/nwserv/.volcache +40 /var/spool/nwserv/.volcache # 41 = path for share/lock files 41 /var/spool/nwserv/.locks # 42 = path for spool dir, e.g. internal print queue handling 42 /var/spool/nwserv # # -# 45 = path for bindery file's -45 /etc -# 46 = path for attribute handling and later trustees -46 /var/lib/nwserv/attrib +# 45 = path for bindery file's +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 # Tables for DOS->Unix names translation & upper/lowercase translations diff --git a/examples/nwopt b/examples/nwopt index 0445546..a0ebd17 100644 --- a/examples/nwopt +++ b/examples/nwopt @@ -1,6 +1,7 @@ -# example for nwopt file. +# example for nwopt file. +# !!!! NOT USED !!!!! # -# last changed: 18-Nov-97 +# last changed: 10-May-98 # # Syntax similar like nwserv.conf file. # diff --git a/examples/unxcomm.c b/examples/unxcomm.c index 6de7165..c191eea 100644 --- a/examples/unxcomm.c +++ b/examples/unxcomm.c @@ -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 +#include #include #include #include - +#include +#include +#include +#include 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))) - size+=l; - + 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) { diff --git a/extpipe.c b/extpipe.c index 402b4a8..8da75cd 100644 --- a/extpipe.c +++ b/extpipe.c @@ -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); } - execvp(buf, argv); + 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)) { - kill(fp->command_pid, SIGTERM); - 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); + else if (!tries) + kill(fp->command_pid, SIGKILL); + sleep(1); } - kill(fp->command_pid, SIGKILL); 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'", diff --git a/extpipe.h b/extpipe.h index 3d1faf8..39c7866 100644 --- a/extpipe.h +++ b/extpipe.h @@ -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 diff --git a/ftrustee.c b/ftrustee.c new file mode 100644 index 0000000..848d72d --- /dev/null +++ b/ftrustee.c @@ -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); +} + diff --git a/ipxif.c b/ipxif.c new file mode 100644 index 0000000..308e59f --- /dev/null +++ b/ipxif.c @@ -0,0 +1,197 @@ +/* inserted by Boris Popov */ +#include +#include +#include +#include +#include + +#include +#ifndef if_mtu +# include +#endif +#include +#include +#include + +/* IPX */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#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); + } +} + diff --git a/makefile.unx b/makefile.unx index 52aa92b..1bb5203 100644 --- a/makefile.unx +++ b/makefile.unx @@ -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 -EMUTLIOBJ=emutli$(O) -EMUTLIOBJ1=emutli1$(O) -# if INTERNAL_RIP_SAP -NWROUTE_O=nwroute$(O) +# 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) +# 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 \ diff --git a/namspace.c b/namspace.c index bf5e7cf..76f2c07 100644 --- a/namspace.c +++ b/namspace.c @@ -1,4 +1,4 @@ -/* namspace.c 01-Feb-98 : NameSpace Services, mars_nwe */ +/* namspace.c 21-Apr-00 : NameSpace Services, mars_nwe */ /* !!!!!!!!!!!! NOTE !!!!!!!!!! */ /* Its still dirty, but it should work fairly well */ @@ -20,6 +20,14 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* history since 21-Apr-00 + * + * mst:21-Apr-00: fixed routine 0x57/0x18, Get Name Spaces Loaded + * count_namespaces is word field, not byte. + * + * + */ + #include "net.h" #include #include @@ -31,6 +39,7 @@ #include "nwvolume.h" #include "connect.h" #include "nwattrib.h" +#include "trustee.h" #include "nwconn.h" #include "nwfile.h" #include "unxfile.h" @@ -58,7 +67,7 @@ typedef struct { } DIR_SEARCH_STRUCT; typedef struct { - uint32 basehandle; + uint32 basehandle; int slot; /* act slot in table */ int locked; /* if locked then do not remove */ /* and do not move till end */ @@ -169,7 +178,8 @@ static char *xnwpath_2_unix(N_NW_PATH *nwpath, int modus, errorp(0, "xnwpath_2_unix", "volume=%d not ok", volume); len = strlen(errorstr); unixname=xmalloc(len_extra+allocate_extra+len+10); - strcpy(unixname, errorstr); + memcpy(unixname, errorstr,len); + unixname[len] = '\0'; } else { int m = ((modus & 1) && nwpath->fn > nwpath->path) /* last path = fn */ ? nwpath->fn - nwpath->path @@ -212,10 +222,12 @@ static char *xnwpath_2_unix(N_NW_PATH *nwpath, int modus, #define nwpath_2_unix(nwpath, modus) \ xnwpath_2_unix((nwpath), (modus), 0, NULL) -#define nwpath_2_unix1(nwpath, modus, extrabytes) \ - xnwpath_2_unix((nwpath), (modus), (extrabytes), NULL) -#define nwpath_2_unix2(nwpath, modus, extrabytes, extrastr) \ - xnwpath_2_unix((nwpath), (modus), (extrabytes), extrastr) +#define alloc_nwpath2unix(nwpath, modus) \ + xnwpath_2_unix((nwpath), (modus), 1, NULL) +#define alloc_nwpath2unix_big(nwpath, modus) \ + xnwpath_2_unix((nwpath), (modus), 258, NULL) +#define alloc_nwpath2unix_extra(nwpath, modus, extrastr) \ + xnwpath_2_unix((nwpath), (modus), 1, extrastr) char *debug_nwpath_name(N_NW_PATH *p) /* only for debugging */ @@ -224,7 +236,7 @@ char *debug_nwpath_name(N_NW_PATH *p) static char *nwpathname=NULL; char volname[300]; int len; - if (nw_get_volume_name(p->volume, volname) < 1) + if (nw_get_volume_name(p->volume, volname, sizeof(volname)) < 1) sprintf(volname, "<%d=NOT-OK>", (int)p->volume); len = strlen(volname) + strlen(p->path) + strlen(p->fn) + 40; xfree(nwpathname); @@ -241,8 +253,15 @@ char *debug_nwpath_name(N_NW_PATH *p) static int nwp_stat(N_NW_PATH *nwpath, char *debstr) { - uint8 *uname=nwpath_2_unix1(nwpath, 2, 1); + uint8 *uname=alloc_nwpath2unix(nwpath, 2); int result=stat(uname, &(nwpath->statb)); + + if (result && errno == EACCES){ /* mst:14-Apr-00 */ + seteuid(0); + result = stat(uname, &(nwpath->statb)); + reseteuid(); + } + if (nw_debug) { char xdebstr[2]; if (!debstr) { @@ -258,6 +277,7 @@ static int nwp_stat(N_NW_PATH *nwpath, char *debstr) return(result); } + static int downsort_dbe_entries(int dbase) { DIR_BASE_ENTRY **dbep=&(dir_base[dbase]); @@ -282,10 +302,10 @@ static void put_dbe_to_disk(DIR_BASE_ENTRY *dbe) char volname[100]; int l; uint8 inode_uc[4]; -#if 0 +#if 0 int voloptions=get_volume_options(dbe->nwpath.volume); -#endif - if (nw_get_volume_name(dbe->nwpath.volume, volname) < 1) +#endif + if (nw_get_volume_name(dbe->nwpath.volume, volname, sizeof(volname)) < 1) return; U32_TO_BE32(dbe->nwpath.statb.st_ino, inode_uc); l=sprintf(buf, "%s/%s/%x/%x/%x/%x/%x", path_vol_inodes_cache, volname, @@ -293,8 +313,8 @@ static void put_dbe_to_disk(DIR_BASE_ENTRY *dbe) (voloptions & VOL_OPTION_IS_HOME) ? act_connection : 0, #else 0, -#endif - dbe->nwpath.statb.st_dev, +#endif + (int) dbe->nwpath.statb.st_dev, (int) inode_uc[0], (int) inode_uc[1], (int) inode_uc[2]); @@ -312,10 +332,10 @@ static void del_dbe_from_disk(DIR_BASE_ENTRY *dbe) char buf[255]; char volname[100]; uint8 inode_uc[4]; -#if 0 +#if 0 int voloptions=get_volume_options(dbe->nwpath.volume); -#endif - if (nw_get_volume_name(dbe->nwpath.volume, volname) < 1) +#endif + if (nw_get_volume_name(dbe->nwpath.volume, volname, sizeof(volname) ) < 1) return; U32_TO_BE32(dbe->nwpath.statb.st_ino, inode_uc); sprintf(buf, "%s/%s/%x/%x/%x/%x/%x/%x", path_vol_inodes_cache, volname, @@ -324,7 +344,7 @@ static void del_dbe_from_disk(DIR_BASE_ENTRY *dbe) #else 0, #endif - dbe->nwpath.statb.st_dev, + (int) dbe->nwpath.statb.st_dev, (int) inode_uc[0], (int) inode_uc[1], (int) inode_uc[2], @@ -343,10 +363,10 @@ static int get_dbe_data_from_disk(int volume, char volname[100]; int l; uint8 inode_uc[4]; -#if 0 +#if 0 int voloptions=get_volume_options(volume); -#endif - if (nw_get_volume_name(volume, volname) < 1) { +#endif + if (nw_get_volume_name(volume, volname, sizeof(volname) ) < 1) { XDPRINTF((1, 0, "get_dbe_d_f_d: wrong volume=%d", volume)); return (-1); } @@ -356,7 +376,7 @@ static int get_dbe_data_from_disk(int volume, (voloptions & VOL_OPTION_IS_HOME) ? act_connection : 0, #else 0, -#endif +#endif dev, (int) inode_uc[0], (int) inode_uc[1], @@ -366,7 +386,7 @@ static int get_dbe_data_from_disk(int volume, seteuid(0); l=readlink(buf, path, 511); reseteuid(); - + if (l > 0) { path[l]='\0'; return(0); @@ -400,7 +420,7 @@ static DIR_BASE_ENTRY *allocate_dbe_p(int namespace) if (to_use_free > -1) { j = to_use_free; } else if (to_use_file > -1) { - j = to_use_file; + j = to_use_file; /* caching directories is more important than caching files */ } else { while (j && dir_base[--j]->locked) ;; @@ -466,18 +486,18 @@ static int touch_handle_entry_p(DIR_BASE_ENTRY *dbe) return(dbase); } -static void rmdir_from_structures(DIR_BASE_ENTRY *dbe) +static void rmdir_from_structures(char *unname, DIR_BASE_ENTRY *dbe) /* is called after directory is deleted from disk, frees some structures */ { int k=count_dsh; int dev = dbe->nwpath.statb.st_dev; ino_t inode = dbe->nwpath.statb.st_ino; - free_nw_ext_inode(dev, inode); + free_nw_ext_inode(dbe->nwpath.volume, unname, dev, inode); while (k--) { DIR_SEARCH_HANDLE *dsh=dir_search_handles[k]; if (dsh && dsh->inode == inode && dsh->dev == dev) { xfree(dir_search_handles[k]); - if (k+1 == count_dsh) + if (k+1 == count_dsh) count_dsh--; } } @@ -515,12 +535,16 @@ static int add_hpath_to_nwpath(N_NW_PATH *nwpath, #if 0 int perhaps_inode_mode = 0; #endif - XDPRINTF((2, 0, "entry add_hpath_to_nwpath: %s", - debug_nwpath_name(nwpath))); + XDPRINTF((4, 0, "entry add_hpath_to_nwpath: '%s', components = %d", + debug_nwpath_name(nwpath), nwp->components)); while (!result && ++k < nwp->components) { int len = (int) *(pp_pathes++); uint8 *p = pp_pathes; pp_pathes+=len; + + XDPRINTF((5, 0, "component %2d, len=%3d, path='%s'", + k, len, gettmpstr(p, len, 0) )); + if (!len) { /* this means '..' ! */ if (pp > nwpath->path) { pp=strrchr((char*)nwpath->path, '/'); @@ -605,36 +629,41 @@ leave_build_nwpath: NW_VOL *v = &nw_volumes[nwpath->volume]; if (nwpath->namespace == NAME_DOS || nwpath->namespace == NAME_OS2) { if (v->options & VOL_OPTION_IGNCASE /* || perhaps_inode_mode*/) { - int nplen= (int)(pp - nwpath->path) - npbeg; - uint8 unixname[1024]; /* should be enough */ - memcpy(unixname, v->unixname, v->unixnamlen); - strcpy(unixname+v->unixnamlen, nwpath->path); - pp=unixname+v->unixnamlen; - if (nwpath->namespace == NAME_OS2) { - dos2unixcharset(pp); - pp+=npbeg; - mangle_os2_name(v, unixname, pp); - if (nplen > 0) { - unix2doscharset(pp); - memcpy(nwpath->path+npbeg, pp, nplen); + int nplen = (int)(pp - nwpath->path) - npbeg; + if (nplen > 0) { /* mst:13-Apr-00 */ + uint8 unixname[1024]; /* should be enough */ + memcpy(unixname, v->unixname, v->unixnamlen); + strmaxcpy(unixname+v->unixnamlen, nwpath->path, + sizeof(unixname) -1 - v->unixnamlen); + pp = unixname+v->unixnamlen; + if (nwpath->namespace == NAME_OS2) { + dos2unixcharset(pp); + pp += npbeg; + mangle_os2_name(v, unixname, pp); + if (nplen > 0) { + unix2doscharset(pp); + memcpy(nwpath->path+npbeg, pp, nplen); + } + XDPRINTF((5,0, "Mangle OS/2 unixname='%s'", unixname)); + } else if (nwpath->namespace == NAME_DOS) { + dos2unixcharset(pp); + pp += npbeg; + + if (v->options & VOL_OPTION_DOWNSHIFT) + down_fn(pp); + else + up_fn(pp); + + mangle_dos_name(v, unixname, pp); + + if (nplen > 0) { + unix2doscharset(pp); + memcpy(nwpath->path+npbeg, pp, nplen); + } + XDPRINTF((5,0, "Mangle DOS unixname='%s'", unixname)); } - XDPRINTF((5,0, "Mangle OS/2 unixname='%s'", unixname)); - } else if (nwpath->namespace == NAME_DOS) { - dos2unixcharset(pp); - pp+=npbeg; - - if (v->options & VOL_OPTION_DOWNSHIFT) - down_fn(pp); - else - up_fn(pp); - - mangle_dos_name(v, unixname, pp); - - if (nplen > 0) { - unix2doscharset(pp); - memcpy(nwpath->path+npbeg, pp, nplen); - } - XDPRINTF((5,0, "Mangle DOS unixname='%s'", unixname)); + } else { + XDPRINTF((5,0, "no mangeling, nplen=%d", nplen)); } } else { if (v->options & VOL_OPTION_DOWNSHIFT) @@ -650,7 +679,7 @@ leave_build_nwpath: } } } - XDPRINTF((2, 0, "add_hpath_to_nwpath: result=0x%x, %s", + XDPRINTF((4, 0, "add_hpath_to_nwpath: result=0x%x, %s", result, debug_nwpath_name(nwpath))); return(result); } @@ -672,6 +701,18 @@ static uint32 name_2_base(N_NW_PATH *nwpath, int namespace, int no_stat) return(basehandle); } +static int volume_supports_namespace(int volume, int namespace) +{ + int voloptions = get_volume_options(volume); + if ( ( (namespace&NAME_OS2) && !(VOL_NAMESPACE_OS2&voloptions) ) + || ( (namespace&NAME_NFS) && !(VOL_NAMESPACE_NFS&voloptions) ) ) { + XDPRINTF((2, 0, "wrong namespace=%d, voloptions=0x%x, volume=%d", + namespace, voloptions, volume)); + return(-0xbf); /* invalid namespace */ + } + return(0); +} + static int add_dbe_entry(int namspace, int volume, uint32 basehandle, uint8 *path, struct stat *stb) @@ -685,7 +726,7 @@ static int add_dbe_entry(int namspace, int volume, dbe->nwpath.volume = volume; dbe->basehandle = basehandle; if (path) { - strcpy(dbe->nwpath.path, path); + xstrcpy(dbe->nwpath.path, path); norm_nwpath_fn(&(dbe->nwpath)); } if (stb) @@ -725,7 +766,7 @@ static int find_base_entry(int volume, uint32 basehandle) } } } - + if (0 < ino) { struct stat statb; uint8 path[512]; @@ -744,7 +785,7 @@ static int find_base_entry(int volume, uint32 basehandle) } - XDPRINTF((1, 0, "Could not find path of vol=%d, base=0x%x, dev=0x%x, inode=%d", + XDPRINTF((1, 0, "Could not find path of vol=%d, base=0x%x, dev=0x%x, inode=%d", volume, basehandle, dnm.dev, ino)); return(-0x9b); } @@ -756,16 +797,15 @@ static int insert_get_base_entry(N_NW_PATH *nwpath, if (!basehandle && creatmode) { /* now creat the entry (file or dir) */ int result = 0; char *unname = nwpath_2_unix(nwpath, 2); - - if (get_volume_options(nwpath->volume) & - VOL_OPTION_READONLY) return(-0x8a); + int voloptions=get_volume_options(nwpath->volume); + if (voloptions&VOL_OPTION_READONLY) return(-0x8a); if (creatmode & FILE_ATTR_DIR) { /* creat dir */ - if (nw_creat_node(nwpath->volume, unname, 1)) + if (nw_creat_node(nwpath->volume, unname, 1)) result=-0x84; } else { /* creat file */ - if (nw_creat_node(nwpath->volume, unname, 0)) + if (nw_creat_node(nwpath->volume, unname, 0)) result=-0x84; } if (result) return(result); @@ -801,7 +841,8 @@ static int build_base(int namespace, NW_HPATH *nwp, uint8 *pathes, int mode, - uint8 *rets) + uint8 *rets, + int size_rets) /* * routine returns the actual dbe entry offset or @@ -827,7 +868,7 @@ static int build_base(int namespace, if (-1 < (result = find_base_entry(nwp->volume, GET_32(nwp->base)))) { DIR_BASE_ENTRY *e = dir_base[result]; nwpath->volume = nwp->volume; - strcpy(nwpath->path, e->nwpath.path); + xstrcpy(nwpath->path, e->nwpath.path); result = 0; } else if (!GET_32(nwp->base)) { nwpath->volume = nwp->volume; @@ -837,31 +878,35 @@ static int build_base(int namespace, XDPRINTF((4, 0, "build_base with basehandle=%ld, result=0x%x", GET_32(nwp->base), result)); } else if (nwp->flag != 0xff) - result=-0xff; + result=-0x9c; /* wrong path */ + if (!result) { nwpath->namespace = namespace; - - if ((result = add_hpath_to_nwpath(nwpath, nwp, pathes)) > -1) { + if ((result = add_hpath_to_nwpath(nwpath, nwp, pathes)) > -1 && namespace) { + int lresult = volume_supports_namespace(nwpath->volume, namespace); + if (lresult) + result = lresult; + } + if (result > -1) { char *pp=strrchr((char*)nwpath->path, '/'); if (mode) { if (pp) { - if (rets) strcpy(rets, pp+1); + if (rets) strmaxcpy(rets, pp+1, size_rets-1); *(pp)=0; pp=strrchr((char*)nwpath->path, '/'); } else { - if (rets) strcpy(rets, nwpath->path); + if (rets) strmaxcpy(rets, nwpath->path, size_rets-1); *(nwpath->path) = '\0'; } } nwpath->fn = (pp) ? (uint8*)pp+1 : nwpath->path; result = insert_get_base_entry(nwpath, namespace, 0); } - } return(result); } -static int build_dos_name(DIR_BASE_ENTRY *e, uint8 *fname) +static int build_dos_name(DIR_BASE_ENTRY *e, uint8 *fname, int size_fname) { uint8 *ss=e->nwpath.fn; int len=0; @@ -897,7 +942,7 @@ static int build_dos_name(DIR_BASE_ENTRY *e, uint8 *fname) } } if (is_ok) { - strcpy(fname, e->nwpath.fn); + strmaxcpy(fname, e->nwpath.fn, size_fname-1); up_fn(fname); return(strlen(fname)); } else { @@ -980,7 +1025,7 @@ int nw_generate_dir_path(int namespace, /* returns Volume Number >=0 or errcode < 0 if error */ { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; U32_TO_32(dbe->basehandle, ns_dir_base); /* LOW - HIGH */ @@ -989,7 +1034,7 @@ int nw_generate_dir_path(int namespace, } else { U32_TO_32(dbe->basehandle, dos_dir_base); } - XDPRINTF((3, 0, "nw_generate_dir_path path=%s, result=%d, basehandle=0x%x", + XDPRINTF((4, 0, "nw_generate_dir_path path=%s, result=%d, basehandle=0x%x", debug_nwpath_name(&(dbe->nwpath)), result, dbe->basehandle)); result= dbe->nwpath.volume; } else { @@ -999,136 +1044,135 @@ int nw_generate_dir_path(int namespace, } static int build_dir_info(DIR_BASE_ENTRY *dbe, + char *unixname, int namespace, uint32 infomask, uint8 *p) { - N_NW_PATH *nwpath=&(dbe->nwpath); - struct stat *stb=&(nwpath->statb); - int result = 76; /* minimumsize */ - uint32 owner = get_file_owner(stb); - int voloptions = get_volume_options(nwpath->volume); + N_NW_PATH *nwpath = &(dbe->nwpath); + int result = volume_supports_namespace(nwpath->volume, namespace); + if (!result) { + struct stat *stb=&(nwpath->statb); + uint32 owner = get_file_owner(stb); + int voloptions = get_volume_options(nwpath->volume); - memset(p, 0, result+2); + result = 76; /* minimumsize */ + memset(p, 0, result+2); - if ( (!S_ISDIR(stb->st_mode)) - && (voloptions & VOL_OPTION_IS_PIPE) ) { - (void)time(&(stb->st_mtime)); - stb->st_size = 0x70000000|(stb->st_mtime&0xfffffff); - stb->st_atime = stb->st_mtime; - } + if ( (!S_ISDIR(stb->st_mode)) + && (voloptions & VOL_OPTION_IS_PIPE) ) { + (void)time(&(stb->st_mtime)); + stb->st_size = 0x70000000|(stb->st_mtime&0xfffffff); + stb->st_atime = stb->st_mtime; + } - if (infomask & INFO_MSK_DATA_STREAM_SPACE) { - U32_TO_32(stb->st_size, p); - } - p += 4; + if (infomask & INFO_MSK_DATA_STREAM_SPACE) { + U32_TO_32(stb->st_size, p); + } + p += 4; - if (infomask & INFO_MSK_ATTRIBUTE_INFO) { -#if NEW_ATTRIB_HANDLING - uint32 attrib = get_nw_attrib_dword(stb, voloptions); -#else - uint32 attrib = ( (!S_ISDIR(stb->st_mode)) - && (voloptions & VOL_OPTION_IS_PIPE) ) - ? (uint32) FILE_ATTR_SHARE|FILE_ATTR_A - : (uint32) un_nw_attrib(stb, 0, 0); -#endif - U32_TO_32(attrib, p); - p += 4; - U16_TO_16((uint16)(attrib & 0xFFFF), p); - p += 2; - } else p+=6; + if (infomask & INFO_MSK_ATTRIBUTE_INFO) { + uint32 attrib = get_nw_attrib_dword(nwpath->volume, unixname, stb); + U32_TO_32(attrib, p); + p += 4; + U16_TO_16((uint16)(attrib & 0xFFFF), p); + p += 2; + } else p+=6; - if (infomask & INFO_MSK_DATA_STREAM_SIZE) { - U32_TO_32(stb->st_size, p); - } - p +=4; - - if (infomask & INFO_MSK_TOTAL_DATA_STREAM_SIZE) { - U32_TO_32(stb->st_size, p); + if (infomask & INFO_MSK_DATA_STREAM_SIZE) { + U32_TO_32(stb->st_size, p); + } p +=4; - U16_TO_16(0, p); - p +=2; - } else p+=6; - if (infomask & INFO_MSK_CREAT_INFO) { - un_time_2_nw(stb->st_mtime, p, 0); - p +=2; - un_date_2_nw(stb->st_mtime, p, 0); - p +=2; - U32_TO_BE32(owner, p); /* HI-LOW ! */ - p +=4; - } else p+=8; + if (infomask & INFO_MSK_TOTAL_DATA_STREAM_SIZE) { + U32_TO_32(stb->st_size, p); + p +=4; + U16_TO_16(0, p); + p +=2; + } else p+=6; - if (infomask & INFO_MSK_MODIFY_INFO) { - un_time_2_nw(stb->st_mtime, p, 0); - p +=2; - un_date_2_nw(stb->st_mtime, p, 0); - p +=2; - U32_TO_BE32(owner, p); /* HI-LOW ! */ - p +=4; - un_date_2_nw(stb->st_atime, p, 0); /* access date */ - p +=2; - } else p+=10; + if (infomask & INFO_MSK_CREAT_INFO) { + un_time_2_nw(stb->st_mtime, p, 0); + p +=2; + un_date_2_nw(stb->st_mtime, p, 0); + p +=2; + U32_TO_BE32(owner, p); /* HI-LOW ! */ + p +=4; + } else p+=8; - if (infomask & INFO_MSK_ARCHIVE_INFO) { - un_time_2_nw(0, p, 0); - p +=2; - un_date_2_nw(0, p, 0); - p +=2; - U32_TO_BE32(0, p); /* HI-LOW */ - p +=4; - } else p+=8; + if (infomask & INFO_MSK_MODIFY_INFO) { + un_time_2_nw(stb->st_mtime, p, 0); + p +=2; + un_date_2_nw(stb->st_mtime, p, 0); + p +=2; + U32_TO_BE32(owner, p); /* HI-LOW ! */ + p +=4; + un_date_2_nw(stb->st_atime, p, 0); /* access date */ + p +=2; + } else p+=10; - if (infomask & INFO_MSK_RIGHTS_INFO) { /* eff. rights ! */ - U16_TO_16( un_nw_rights(stb), p); - } - p +=2; + if (infomask & INFO_MSK_ARCHIVE_INFO) { + un_time_2_nw(0, p, 0); + p +=2; + un_date_2_nw(0, p, 0); + p +=2; + U32_TO_BE32(0, p); /* HI-LOW */ + p +=4; + } else p+=8; - if (infomask & INFO_MSK_DIR_ENTRY_INFO) { - U32_TO_32(dbe->basehandle, p); - p +=4; + if (infomask & INFO_MSK_RIGHTS_INFO) { /* eff. rights ! */ + U16_TO_16(tru_get_eff_rights(nwpath->volume, unixname, stb), p); + } + p +=2; + + if (infomask & INFO_MSK_DIR_ENTRY_INFO) { + U32_TO_32(dbe->basehandle, p); + p +=4; #if 0 - U32_TO_32(dbe->basehandle, p); + U32_TO_32(dbe->basehandle, p); #else - U32_TO_32(name_2_base(nwpath, NAME_DOS, 1), p); + U32_TO_32(name_2_base(nwpath, NAME_DOS, 1), p); #endif - p +=4; - U32_TO_32(nwpath->volume, p); - p +=4; - } else p+=12; + p +=4; + U32_TO_32(nwpath->volume, p); + p +=4; + } else p+=12; - if (infomask & INFO_MSK_EXT_ATTRIBUTES) { - U32_TO_32(0, p); /* Ext Attr Data Size */ - p +=4; - U32_TO_32(0, p); /* Ext Attr Count */ - p +=4; - U32_TO_32(0, p); /* Ext Attr Key Size */ - p +=4; - } else p+=12; + if (infomask & INFO_MSK_EXT_ATTRIBUTES) { + U32_TO_32(0, p); /* Ext Attr Data Size */ + p +=4; + U32_TO_32(0, p); /* Ext Attr Count */ + p +=4; + U32_TO_32(0, p); /* Ext Attr Key Size */ + p +=4; + } else p+=12; - if (infomask & INFO_MSK_NAME_SPACE_INFO){ - U32_TO_32(namespace, p); /* using namespace */ - } - p +=4; + if (infomask & INFO_MSK_NAME_SPACE_INFO){ + U32_TO_32(namespace, p); /* using namespace */ + } + p +=4; - /* ---------------------------------------------- */ - if (infomask & INFO_MSK_ENTRY_NAME) { - result++; - if (namespace == NAME_DOS) { - *p=(uint8) build_dos_name(dbe, p+1); - result += (int) *p; - } else { - *p = (uint8) strlen(nwpath->fn); - if (*p) { - memcpy(p+1, nwpath->fn, (int) *p); + /* ---------------------------------------------- */ + if (infomask & INFO_MSK_ENTRY_NAME) { + result++; + if (namespace == NAME_DOS) { + *p=(uint8) build_dos_name(dbe, p+1, 13 ); result += (int) *p; + } else { + *p = (uint8) strlen(nwpath->fn); + if (*p) { + memcpy(p+1, nwpath->fn, (int) *p); + result += (int) *p; + } } } } - XDPRINTF((3, 0, "build_d_i:space=%d, path=%s, result=%d, handle=0x%x, mask=0x%lx", + XDPRINTF((4, 0, "build_d_i:space=%d, path=%s, result=%d, handle=0x%x, mask=0x%lx", namespace, debug_nwpath_name(nwpath), result, dbe->basehandle, infomask)); return(result); } + + int nw_optain_file_dir_info(int namespace, NW_HPATH *nwp, int destnamspace, int searchattrib, uint32 infomask, @@ -1139,33 +1183,39 @@ int nw_optain_file_dir_info(int namespace, NW_HPATH *nwp, * must return -0xff for file not found ! */ { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; + char *unixname = alloc_nwpath2unix(&(dbe->nwpath), 2); nwp_stat(&(dbe->nwpath), "nw_optain_file_dir_info"); - result = build_dir_info(dbe, destnamspace, infomask, responsedata); - } else { - XDPRINTF((3, 0, "nw_optain_file_dir_info NOT OK result=-0x%x", - -result)); + result = build_dir_info(dbe, unixname, destnamspace, infomask, responsedata); + xfree(unixname); + } + if (result < 0) { + XDPRINTF((3, 0, "nw_optain_file_dir_info NOT OK result=-0x%x", -result)); } return(result); } -int nw_get_eff_rights(int namespace, NW_HPATH *nwp, +static int nsp_get_eff_rights(int namespace, NW_HPATH *nwp, int destnamspace, int searchattrib, uint32 infomask, uint8 *responsedata) { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; - nwp_stat(&(dbe->nwpath), "nw_get_eff_rights"); - U16_TO_16(un_nw_rights(&(dbe->nwpath.statb)), responsedata); + char *unixname = alloc_nwpath2unix(&(dbe->nwpath), 2); + nwp_stat(&(dbe->nwpath), "nsp_get_eff_rights"); + U16_TO_16(tru_get_eff_rights(dbe->nwpath.volume, unixname, + &(dbe->nwpath.statb)), responsedata); responsedata+=2; - result = 2+build_dir_info(dbe, destnamspace, infomask, responsedata); - } else { - XDPRINTF((3, 0, "nw_get_eff_rights NOT OK result=-0x%x", - -result)); + result = build_dir_info(dbe, unixname, destnamspace, infomask, responsedata); + if (result>-1) result+=2; + xfree(unixname); + } + if (result <0 ) { + XDPRINTF((3, 0, "nsp_get_eff_rights NOT OK result=-0x%x", -result)); } return(result); } @@ -1175,7 +1225,7 @@ static int nw_init_search(int namespace, uint8 *pathes, uint8 *responsedata) { - int result = build_base(namespace, nwp, pathes, 0, NULL); + int result = build_base(namespace, nwp, pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; result = S_ISDIR(dbe->nwpath.statb.st_mode) ? 0 : -0xff; @@ -1201,16 +1251,159 @@ static int get_add_new_entry(DIR_BASE_ENTRY *qbe, int namespace, N_NW_PATH nwpath; nwpath.volume = qbe->nwpath.volume; nwpath.namespace = namespace; - strcpy(nwpath.path, qbe->nwpath.path); + xstrcpy(nwpath.path, qbe->nwpath.path); nwpath.fn = nwpath.path+strlen(nwpath.path); if (nwpath.fn > nwpath.path && *(nwpath.fn-1) != '/') { *(nwpath.fn) = '/'; *(++nwpath.fn) = '\0'; } - strcpy(nwpath.fn, path); + strmaxcpy(nwpath.fn, path, + sizeof(nwpath.path) - (int) (nwpath.fn - nwpath.path) -1); return(insert_get_base_entry(&nwpath, namespace, creatmode)); } +/* the new fn_dos_match routine from Andrew do not work ok + * for namespace dos searches, because namespace searches do + * something like "0xff *" to match all files. + * or "0xff ? 0xff ? ... 0xff ? . 0xff ? 0xff ? 0xff ?" to match + * 12345678.abc + */ + +static int x_str_match(uint8 *s, uint8 *p, int soptions) +{ + uint8 pc, sc; + uint state = 0; + uint8 anf, ende; + int not = 0; + uint found = 0; + while ( (pc = *p++) != 0) { + + if (state != 100) { + if (pc == 255 && (*p == '*' || *p == '?' + || *p==0xaa || *p==0xae || *p==0xbf || *p=='.')) { + pc=*p++; + } + + switch (pc) { + case 0xaa: pc='*'; break; + case 0xae: pc='.'; break; + case 0xbf: pc='?'; break; + } + } + + switch (state){ + case 0 : + switch (pc) { + case '\\': /* any following char */ + if (*p++ != *s++) return(0); + break; + + case '?' : if (!*s || (sc = *s++) == '.') + state = 10; + break; + + case '.' : if (*s && pc != *s++) return(0); + break; + + case '*' : if (!*p) return(1); /* last star */ + while (*s) { + if (x_str_match(s, p, soptions) == 1) return(1); + else if (*s == '.') return(0); + ++s; + } + state = 30; + break; + + case '[' : if ( (*p == '!') || (*p == '^') ){ + ++p; + not = 1; + } + state = 100; + continue; + + default : /* 'normal' chars */ + if (soptions & VOL_OPTION_IGNCASE) { + if (!dfn_imatch(*s, pc)) + return(0); + } else if (pc != *s) return(0); + s++; + break; + + } /* switch */ + break; + + case 10 : if (pc != '*' && pc != '?' ) { + if (pc == '.') + state = 0; + else return(0); + } + break; + + case 30: if (pc != '.') return(0); + state = 31; + break; + + case 31: if (pc != '*' ) return(0); + break; + + case 100 : /* Bereich von Zeichen */ + sc = *s++; + found = not; + if (!sc) return(0); + do { + if (pc == '\\') pc = *(p++); + if (!pc) return(0); + anf = pc; + if (*p == '-' && *(p+1) != ']'){ + ende = *(++p); + p++; + } + else ende = anf; + if (found == not) { /* only if not found */ + if (anf == sc || (anf <= sc && sc <= ende)) + found = !not; + } + } while ((pc = *(p++)) != ']'); + if (! found ) return(0); + not = 0; + found = 0; + state = 0; + break; + + default : break; + } /* switch */ + } /* while */ + if (*s=='.' && *(s+1)=='\0') return(1); /* I hope this is right */ + return ( (*s) ? 0 : 1); +} + +static int fn_dos_match_old(uint8 *s, uint8 *p, int options) +{ + uint8 *ss=s; + int len=0; + int pf=0; + for (; *ss; ss++){ + if (*ss == '.') { + if (pf++) return(0); /* no 2. point */ + len=0; + } else { + ++len; + if ((pf && len > 3) || len > 8) return(0); + + if (!(options & VOL_OPTION_IGNCASE)){ + if (options & VOL_OPTION_DOWNSHIFT){ /* only downshift chars */ + if (*ss >= 'A' && *ss <= 'Z') return(0); + } else { /* only upshift chars */ + if (*ss >= 'a' && *ss <= 'z') return(0); + } + } + + } + } + return(x_str_match(s, p, options)); +} + + static int namespace_fn_match(uint8 *s, uint8 *p, int namespace) /* for *OTHER* namespaces than DOS + OS2 */ { @@ -1298,13 +1491,16 @@ static int namespace_fn_match(uint8 *s, uint8 *p, int namespace) } -static int search_match(struct dirent *dirbuff, +static int search_match(struct dirent *dirbuff, + int volume, int vol_options, int namespace, int inode_search, /* do we search an inode */ uint8 *entry, int searchattrib, + int needs_search_trustee, /* mst: 13-Apr-00 */ uint8 *dname, + int size_dname, DIR_SEARCH_STRUCT *ds) /* returns 1 if match, 0= no match */ @@ -1314,14 +1510,14 @@ static int search_match(struct dirent *dirbuff, uint8 *name=(uint8*)(dirbuff->d_name); struct stat statb; if (namespace == NAME_DOS || namespace == NAME_OS2) { - strcpy(dname, name); + strmaxcpy(dname, name, size_dname-1); unix2doscharset(dname); } else - strcpy(dname, name); + strmaxcpy(dname, name, size_dname-1); XDPRINTF((8,0,"search_match, Name='%s' dname='%s'", name, dname)); if (!inode_search) { if (namespace == NAME_DOS) { - flag = (*name != '.' && fn_dos_match(dname, entry, vol_options)); + flag = (*name != '.' && fn_dos_match_old(dname, entry, vol_options)); } else if (namespace == NAME_OS2) { flag = (*name != '.' || (*(name+1) != '.' && *(name+1) != '\0' )) && fn_os2_match(dname, entry, vol_options); @@ -1331,22 +1527,41 @@ static int search_match(struct dirent *dirbuff, } } else flag = (dirbuff->d_ino == inode_search); - + if (flag) { - strcpy(ds->kpath, name); + int statflag; + strmaxcpy(ds->kpath, name, 255); XDPRINTF((7,0,"search_match, Name found=%s unixname=%s", name, ds->unixname)); - if (!stat(ds->unixname, &statb)) { - flag = (searchattrib & W_SEARCH_ATTR_ALL) == W_SEARCH_ATTR_ALL; - if (!flag) { - if (S_ISDIR(statb.st_mode)) - flag=(searchattrib & FILE_ATTR_DIR); - else - flag = !(searchattrib & FILE_ATTR_DIR); + + statflag = stat(ds->unixname, &statb); + if (statflag && errno == EACCES) { /* mst:21-Apr-00 */ + seteuid(0); + statflag = stat(ds->unixname, &statb); + reseteuid(); + } + + if (!statflag) { + if (needs_search_trustee /* mst: 13-Apr-00 */ + && tru_eff_rights_exists(volume, ds->unixname, &statb, TRUSTEE_T)){ + flag = 0; + XDPRINTF((2,0,"search_match: no trustee rights fn='%s'", ds->unixname)); } - if (!flag) { - XDPRINTF((10, 0, "type = %s not ok searchattrib=0x%x", - S_ISDIR(statb.st_mode) ? "DIR" :"FILE" ,searchattrib)); + if (flag) { + flag = (searchattrib & W_SEARCH_ATTR_ALL) == W_SEARCH_ATTR_ALL; + if (!flag) { + int do_searchdir = ((searchattrib & W_SEARCH_ATTR_DIR) + || (searchattrib & FILE_ATTR_DIR)) + ? 1 : 0; + if (S_ISDIR(statb.st_mode)) + flag = do_searchdir; + else + flag = !do_searchdir; + } + if (!flag) { + XDPRINTF((10, 0, "type = %s not ok searchattrib=0x%x", + S_ISDIR(statb.st_mode) ? "DIR" :"FILE" ,searchattrib)); + } } } else { XDPRINTF((2,0,"search_match: stat error fn='%s'", @@ -1371,24 +1586,34 @@ int nw_search_file_dir(int namespace, int datastream, DIR_BASE_ENTRY *dest_dbe=NULL; DIR_SEARCH_HANDLE *dsh=NULL; DIR_BASE_ENTRY *dbe=NULL; - + uint8 *unixname =NULL; int sequence; + int no_search_trustee = 0; *perhaps_more = 0; *count = 0; MDEBUG(D_FN_SEARCH, { char fname[300]; strmaxcpy(fname, path, min(sizeof(fname)-1, len)); - xdprintf(1,0,"nwsfd:sequence=%d,%d, base=%d, attrib=0x%x, fn=`%s`", - *psequence & 0xff, *psequence >> 8, basehandle, + xdprintf(1,0,"nwsfd:sequence=%d,%d, base=%d, attrib=0x%x, fn=`%s`", + *psequence & 0xff, *psequence >> 8, basehandle, searchattrib, fname); }) - + if (len > 255) result=-0x9c; /* we say wrong path here */ - else if (result > -1) { + + if (result > -1) { + dbe=dir_base[result]; + unixname = (uint8*)alloc_nwpath2unix_big(&(dbe->nwpath), 2); + if ( (no_search_trustee = tru_eff_rights_exists(dbe->nwpath.volume, unixname, + &(dbe->nwpath.statb), TRUSTEE_F)) + && !(no_search_trustee&TRUSTEE_T) ) + result=-0xff; /* no search rights */ + } + if (result > -1) { dbe=dir_base[result]; if (*psequence == MAX_U32) { - *psequence=new_search_handle(dbe->nwpath.statb.st_dev, + *psequence=new_search_handle(dbe->nwpath.statb.st_dev, dbe->nwpath.statb.st_ino); MDEBUG(D_FN_SEARCH, { xdprintf(1,0,"nwsfd:got new search seqence=%d", *psequence); @@ -1396,16 +1621,16 @@ int nw_search_file_dir(int namespace, int datastream, } sequence = *psequence >> 8; *psequence &= 0xff; - + if (*psequence < count_dsh) { dsh=dir_search_handles[*psequence]; if (dsh && (dbe->nwpath.statb.st_dev != dsh->dev || dbe->nwpath.statb.st_ino != dsh->inode)) dsh=NULL; } - + if (!dsh) { - *psequence=new_search_handle(dbe->nwpath.statb.st_dev, + *psequence=new_search_handle(dbe->nwpath.statb.st_dev, dbe->nwpath.statb.st_ino); *psequence &= 0xff; dsh=dir_search_handles[*psequence]; @@ -1414,9 +1639,13 @@ int nw_search_file_dir(int namespace, int datastream, if (NULL != dsh) { DIR_SEARCH_STRUCT *ds=(DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT)); - ds->unixname = (uint8*)nwpath_2_unix1(&(dbe->nwpath), 2, 258); - - if (NULL != (ds->fdir = opendir(ds->unixname)) ) { + ds->unixname = unixname; + if (NULL == (ds->fdir = opendir(ds->unixname)) ) { + seteuid(0); + ds->fdir=opendir(ds->unixname); + reseteuid(); + } + if (NULL != ds->fdir) { uint8 entry[257]; uint8 *pe=entry; int have_wild=0; /* do we have a wildcard entry */ @@ -1471,39 +1700,42 @@ int nw_search_file_dir(int namespace, int datastream, } if (dsh->dirpos) { - seekdir(ds->fdir, dsh->dirpos); + SEEKDIR(ds->fdir, dsh->dirpos); if (( (dirbuff=readdir(ds->fdir)) == NULL - || (dirbuff->d_ino != dsh->found_inode)) + || (dirbuff->d_ino != dsh->found_inode)) && dsh->found_inode>0) { - seekdir(ds->fdir, 0L); + SEEKDIR(ds->fdir, 0L); XDPRINTF((5, 0, "dirbuff->d_ino %d != dsh->found_inode=%d ", (dirbuff)?dirbuff->d_ino:0, dsh->found_inode)); dsh->lastsequence=0; - while((dirbuff=readdir(ds->fdir)) != NULL + while((dirbuff=readdir(ds->fdir)) != NULL && dirbuff->d_ino != dsh->found_inode) dsh->lastsequence++; } if (!dirbuff) /* inode not found */ - seekdir(ds->fdir, 0L); - } + SEEKDIR(ds->fdir, 0L); + } if (dirbuff==NULL) { dsh->lastsequence=0; while ((dirbuff=readdir(ds->fdir)) != NULL && dsh->lastsequence < sequence) dsh->lastsequence++; } - + while (dirbuff!=NULL) { uint8 dname[257]; if (search_match( dirbuff, + volume, vol_options, namespace, inode_search, entry, searchattrib, + no_search_trustee, /* mst: 13-Apr-00 */ dname, + sizeof(dname), ds)) { - if ((dest_entry = get_add_new_entry(dbe, namespace, dname, 0)) > -1) + if ((dest_entry = get_add_new_entry(dbe, namespace, dname, 0)) > -1) break; else { XDPRINTF((2, 0, "nw_search_file_dir:Cannot add entry '%s'", entry)); @@ -1516,13 +1748,18 @@ int nw_search_file_dir(int namespace, int datastream, *(ds->kpath) = '\0'; if (dest_entry > -1) { + char *funixname; dest_dbe=dir_base[dest_entry]; + funixname = alloc_nwpath2unix(&(dbe->nwpath), 2); + (void) nwp_stat(&(dest_dbe->nwpath), "nw_search_file_dir"); - result = build_dir_info(dest_dbe, datastream, + result = build_dir_info(dest_dbe, funixname, datastream, infomask |INFO_MSK_NAME_SPACE_INFO, info); + xfree(funixname); + *count=1; - dsh->dirpos = telldir(ds->fdir); + dsh->dirpos = TELLDIR(ds->fdir); dirbuff = readdir(ds->fdir); dsh->found_inode=0; *perhaps_more=0; @@ -1530,25 +1767,28 @@ int nw_search_file_dir(int namespace, int datastream, while (dirbuff) { uint8 dname[257]; if (search_match( dirbuff, + volume, vol_options, namespace, inode_search, entry, searchattrib, + no_search_trustee, /* mst: 13-Apr-00 */ dname, + sizeof(dname), ds)) { *perhaps_more=0xff; dsh->found_inode=dirbuff->d_ino; break; } - dsh->dirpos = telldir(ds->fdir); + dsh->dirpos = TELLDIR(ds->fdir); dirbuff = readdir(ds->fdir); dsh->lastsequence++; } /* while */ *psequence |= (dsh->lastsequence << 8); if (!*perhaps_more) dsh->idle=MAX_I32-4; XDPRINTF((5, 0, "more=%d, sequence = 0x%x, file=%s,next=%s", - *perhaps_more, *psequence, dest_dbe->nwpath.path, + *perhaps_more, *psequence, dest_dbe->nwpath.path, dirbuff?dirbuff->d_name:"")); } else { dsh->idle = MAX_I32-2; @@ -1562,7 +1802,6 @@ int nw_search_file_dir(int namespace, int datastream, result=-0xff; /* thanks Peter Gerhard :) */ XDPRINTF((5, 0, "could not opendir=`%s`", ds->unixname)); } - xfree(ds->unixname); xfree(ds); } else if (result > -1) result=-0xff; MDEBUG(D_FN_SEARCH, { @@ -1573,6 +1812,7 @@ int nw_search_file_dir(int namespace, int datastream, xdprintf(1, 1,"found='%s'", (dest_dbe) ? (char*) (dest_dbe->nwpath.path) : "" ); } }) + xfree(unixname); return(result); } @@ -1586,24 +1826,33 @@ static int nw_open_creat_file_or_dir( uint8 *responsedata, int task) { - int result = build_base(namespace, nwp, pathes, 0, NULL); + int result = build_base(namespace, nwp, pathes, 0, NULL, 0); int exist = result; uint8 last_part[258]; *last_part='\0'; - if (result < 0 && (opencreatmode & (OPC_MODE_CREAT|OPC_MODE_REPLACE))) { + if (result == -0xff && (opencreatmode & (OPC_MODE_CREAT|OPC_MODE_REPLACE))) { /* do not exist */ - result = build_base(namespace, nwp, pathes, 1, last_part); + result = build_base(namespace, nwp, pathes, 1, last_part, sizeof(last_part)); XDPRINTF((5, 0, "nw_open_c... result=%d, last_part='%s'", result, last_part)); - if (result > -1) + if (result > -1) result = get_add_new_entry(dir_base[result], namespace, last_part, (creatattrib & FILE_ATTR_DIR) ? FILE_ATTR_DIR : 1); } + if (result<0) { + XDPRINTF((5, 0, "nw_open_c... result=0x%x", -result)); + } + /* 16-May-99, if file exist but mode == CREAT then error */ + if (result > -1 && exist > -1 && opencreatmode == OPC_MODE_CREAT) { + result = -0x85; /* No Priv */ + } + if (result > -1) { uint32 fhandle=0L; int actionresult=0; DIR_BASE_ENTRY *dbe=dir_base[result]; if (exist < 0) actionresult |= OPC_ACTION_CREAT; + if (!(creatattrib & FILE_ATTR_DIR)) { int creatmode=0; /* open */ int attrib=0; @@ -1633,12 +1882,16 @@ static int nw_open_creat_file_or_dir( (exist > -1) result=-0x84; if (result > -1) { + char *unixname = alloc_nwpath2unix(&(dbe->nwpath), 2); U32_TO_32(fhandle, responsedata); responsedata += 4; *responsedata =(uint8) actionresult; *(responsedata+1) = 0; responsedata+=2; - result = 6 + build_dir_info(dbe, namespace, infomask, responsedata); + result = build_dir_info(dbe, unixname, namespace, infomask, responsedata); + if (result>-1) + result+=6; + xfree(unixname); } } XDPRINTF((3, 0, "nw_open_creat mode=0x%x, creatattr=0x%x, access=0x%x, attr=0x%x, result=%d", @@ -1652,131 +1905,135 @@ typedef struct { } FUNC_SEARCH; static int func_search_entry(DIR_BASE_ENTRY *dbe, int namespace, - uint8 *path, int len, int searchattrib, + uint8 *path, int len, int searchattrib, int (*fs_func)(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs), FUNC_SEARCH *fs) { int result=-0xff; FUNC_SEARCH fs_local; - DIR_SEARCH_STRUCT *ds=(DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT)); if (!fs) { fs = &fs_local; fs->ubuf = NULL; } fs->searchattrib = searchattrib; - ds->unixname = (uint8*)nwpath_2_unix1(&(dbe->nwpath), 2, 258); - if (NULL != (ds->fdir = opendir(ds->unixname)) ) { - uint8 entry[257]; - uint8 *pe=entry; - int have_wild = 0; /* do we have a wildcard entry */ - int inode_search = 0; - uint8 *is_ap = NULL; /* one after point */ - struct dirent *dirbuff = NULL; - int vol_options = get_volume_options(dbe->nwpath.volume); - ds->kpath = ds->unixname+strlen(ds->unixname); - *(ds->kpath) = '/'; - *(++(ds->kpath)) = '\0'; - dbe->locked++; /* lock dbe */ - - while (len--) { - uint8 c=*path++; - *pe++=c; - if (!have_wild) { - if (c==0xff) { - if (*path == '?' || *path == '*' - || *path == 0xae || *path == 0xbf || *path==0xaa) - have_wild++; - } else if (c == '.') is_ap=pe; + if (!len && ( !dbe->nwpath.path[0] + || (dbe->nwpath.path[0]=='/' && dbe->nwpath.path[1]=='\0'))) { + /* volume path */ + if (searchattrib & (W_SEARCH_ATTR_DIR | FILE_ATTR_DIR)) { + int res = (*fs_func)(dbe, fs); + if (res < 0) result=res; + else result=0; + } + } else { + DIR_SEARCH_STRUCT *ds=(DIR_SEARCH_STRUCT*) xcmalloc(sizeof(DIR_SEARCH_STRUCT)); + ds->unixname = (uint8*)alloc_nwpath2unix_big(&(dbe->nwpath), 2); + if (!tru_eff_rights_exists(dbe->nwpath.volume, ds->unixname, + &(dbe->nwpath.statb), TRUSTEE_F)) { + if (NULL == (ds->fdir = opendir(ds->unixname)) ) { + seteuid(0); + ds->fdir = opendir(ds->unixname); + reseteuid(); } - } - *pe='\0'; + } else ds->fdir=NULL; + if (NULL != ds->fdir) { + uint8 entry[257]; + uint8 *pe=entry; + int have_wild = 0; /* do we have a wildcard entry */ + int inode_search = 0; + uint8 *is_ap = NULL; /* one after point */ + struct dirent *dirbuff = NULL; + int vol_options = get_volume_options(dbe->nwpath.volume); + ds->kpath = ds->unixname+strlen(ds->unixname); + *(ds->kpath) = '/'; + *(++(ds->kpath)) = '\0'; + dbe->locked++; /* lock dbe */ - if ((!have_wild) && is_ap && pe - is_ap == 3 && *is_ap== '_' - && *(is_ap+1) == '_' && *(is_ap+2) == '_') { - *(is_ap -1) = '\0'; - inode_search=atoi(entry); - *(is_ap -1) = '.'; - } - - if ( (namespace == NAME_DOS || namespace == NAME_OS2) - && !(vol_options & VOL_OPTION_IGNCASE) ) { - if (vol_options & VOL_OPTION_DOWNSHIFT) { - down_fn(entry); - } else { - up_fn(entry); - } - } - - while (NULL != (dirbuff=readdir(ds->fdir))) { - uint8 dname[257]; - if (search_match( dirbuff, - vol_options, - namespace, - inode_search, - entry, - searchattrib, - dname, - ds)) { - int dest_entry = get_add_new_entry(dbe, namespace, dname, 0); - if (dest_entry > -1) { - int res = (*fs_func)(dir_base[dest_entry], fs); - if (res < 0) { - result=res; - break; - } else - result=0; - } else { - XDPRINTF((2, 0, "func_search_entry:Cannot add entry '%s'", entry)); + while (len--) { + uint8 c=*path++; + *pe++=c; + if (!have_wild) { + if (c==0xff) { + if (*path == '?' || *path == '*' + || *path == 0xae || *path == 0xbf || *path==0xaa) + have_wild++; + } else if (c == '.') is_ap=pe; } } - } /* while */ - *(ds->kpath) = '\0'; - dbe->locked=0; - closedir(ds->fdir); - } else { /* if NULL != ds->fdir */ - XDPRINTF((5, 0, "func_search_entry:could not opendir=`%s`", ds->unixname)); + *pe='\0'; + + if ((!have_wild) && is_ap && pe - is_ap == 3 && *is_ap== '_' + && *(is_ap+1) == '_' && *(is_ap+2) == '_') { + *(is_ap -1) = '\0'; + inode_search=atoi(entry); + *(is_ap -1) = '.'; + } + + if ( (namespace == NAME_DOS || namespace == NAME_OS2) + && !(vol_options & VOL_OPTION_IGNCASE) ) { + if (vol_options & VOL_OPTION_DOWNSHIFT) { + down_fn(entry); + } else { + up_fn(entry); + } + } + + while (NULL != (dirbuff=readdir(ds->fdir))) { + uint8 dname[257]; + if (search_match( dirbuff, + dbe->nwpath.volume, + vol_options, + namespace, + inode_search, + entry, + searchattrib, + 0, /* mst: 13-Apr-00 */ + dname, + sizeof(dname), + ds)) { + int dest_entry = get_add_new_entry(dbe, namespace, dname, 0); + if (dest_entry > -1) { + int res = (*fs_func)(dir_base[dest_entry], fs); + if (res < 0) { + result=res; + break; + } else + result=0; + } else { + XDPRINTF((2, 0, "func_search_entry:Cannot add entry '%s'", entry)); + } + } + } /* while */ + *(ds->kpath) = '\0'; + dbe->locked=0; + closedir(ds->fdir); + } else { /* if NULL != ds->fdir */ + XDPRINTF((5, 0, "func_search_entry:could not opendir=`%s`", ds->unixname)); + } + xfree(ds->unixname); + xfree(ds); } - xfree(ds->unixname); - xfree(ds); return(result); } - + static int delete_file_dir(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs) /* callbackroutine */ { uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2); - int result; - if (S_ISDIR(dbe->nwpath.statb.st_mode)) { - int voloptions = get_volume_options(dbe->nwpath.volume); - /* directory */ - if (get_nw_attrib_dword(&dbe->nwpath.statb, voloptions) & FILE_ATTR_R) - result = -0x8a; /* don't delete 'readonly' */ - else { - result = rmdir(unname); - if (result < 0) { - switch (errno) { - case EEXIST: result=-0xa0; /* dir not empty */ - default: result=-0x8a; /* No privilegs */ - } - } - } - if (result>-1) { - rmdir_from_structures(dbe); - result = 0; - } - } else { - /* file */ - if (-1 < (result = nw_unlink(dbe->nwpath.volume, unname))) - free_dbe_p(dbe); + int result=nw_unlink_node(dbe->nwpath.volume, unname,&dbe->nwpath.statb); + if (!result) { + if (S_ISDIR(dbe->nwpath.statb.st_mode)) /* directory */ + rmdir_from_structures(unname, dbe); + else /* file */ + free_dbe_p(dbe); } return(result); } - static int nw_delete_file_dir(int namespace, int searchattrib, NW_HPATH *nwp) { uint8 search_entry[258]; - int result = build_base(namespace, nwp, nwp->pathes, 1, search_entry); + int result = build_base(namespace, nwp, nwp->pathes, 1, + search_entry, sizeof(search_entry)); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; if (get_volume_options(dbe->nwpath.volume) & @@ -1791,12 +2048,12 @@ static int nw_delete_file_dir(int namespace, int searchattrib, static int nw_alloc_short_dir_handle(int namespace, int hmode, NW_HPATH *nwp, int task, int *volume) { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; if (S_ISDIR(dbe->nwpath.statb.st_mode)) { result=xinsert_new_dir(dbe->nwpath.volume, dbe->nwpath.path, - dbe->nwpath.statb.st_dev, dbe->nwpath.statb.st_ino, + dbe->nwpath.statb.st_dev, dbe->nwpath.statb.st_ino, 300, hmode, task); *volume=dbe->nwpath.volume; } else result=-0xff; @@ -1807,7 +2064,7 @@ static int nw_alloc_short_dir_handle(int namespace, int hmode, static int nw_set_short_dir_handle(int namespace, int desthandle, NW_HPATH *nwp, int task) { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; if (S_ISDIR(dbe->nwpath.statb.st_mode)) { @@ -1819,6 +2076,151 @@ static int nw_set_short_dir_handle(int namespace, int desthandle, return((result > 0) ? 0 : result); } +typedef struct { + int count; /* count oic */ + NW_OIC *nwoic; +} S_ADD_TRUSTEE_SET; + +static int add_trustee_set(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs) +/* callbackroutine */ +{ + uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2); + S_ADD_TRUSTEE_SET *st=(S_ADD_TRUSTEE_SET*)fs->ubuf; + return(tru_add_trustee_set(dbe->nwpath.volume, unname, + &(dbe->nwpath.statb), + st->count, st->nwoic)); +} + +static int nw_add_trustee_set(int namespace, int searchattrib, + NW_HPATH *nwp, + int trustee_rights, + int count, uint8 *oic) +{ + uint8 search_entry[258]; + int result = build_base(namespace, nwp, nwp->pathes, 1, + search_entry, sizeof(search_entry)); + if (result > -1) { + DIR_BASE_ENTRY *dbe=dir_base[result]; + if (get_volume_options(dbe->nwpath.volume) & + VOL_OPTION_READONLY) result = -0x8a; + else { + FUNC_SEARCH fs; + S_ADD_TRUSTEE_SET st; + NW_OIC *nwoic=st.nwoic=(NW_OIC*)xmalloc(sizeof(NW_OIC)*count); + st.count=0; + fs.ubuf=(uint8*)&st; + while (count--) { + nwoic->id=GET_BE32(oic); + oic += 4; + if (trustee_rights == -1) + nwoic->trustee=GET_16(oic); + else + nwoic->trustee=trustee_rights; + oic+=2; + if (nwoic->id) { + st.count++; + nwoic++; + } + } + result = func_search_entry(dbe, namespace, + search_entry, strlen(search_entry), searchattrib, + add_trustee_set, &fs); + xfree(st.nwoic); + } + } + return(result); +} + +typedef struct { + int count; /* count oic */ + uint32 *ids; +} S_DEL_TRUSTEE_SET; + +static int del_trustee_set(DIR_BASE_ENTRY *dbe, FUNC_SEARCH *fs) +/* callbackroutine */ +{ + uint8 *unname=(uint8*)nwpath_2_unix(&(dbe->nwpath), 2); + int result=0; + S_DEL_TRUSTEE_SET *st=(S_DEL_TRUSTEE_SET*)fs->ubuf; + int k=st->count; + uint32 *ids=st->ids; + while (k--) { + int res=tru_del_trustee(dbe->nwpath.volume, unname, + &(dbe->nwpath.statb), *ids); + if (res < 0) { + result=res; + break; + } + ids++; + } + return(result); +} + +static int nw_del_trustee_set(int namespace, + NW_HPATH *nwp, + int count, uint8 *did) +{ + uint8 search_entry[258]; + int result = build_base(namespace, nwp, nwp->pathes, 1, + search_entry, sizeof(search_entry) ); + if (result > -1) { + DIR_BASE_ENTRY *dbe=dir_base[result]; + if (get_volume_options(dbe->nwpath.volume) & + VOL_OPTION_READONLY) result = -0x8a; + else { + FUNC_SEARCH fs; + S_DEL_TRUSTEE_SET st; + uint32 *ids=st.ids=(uint32*)xmalloc(sizeof(uint32)*count); + st.count=0; + fs.ubuf=(uint8*)&st; + while (count--) { + *ids=GET_BE32(did); + if (*ids) { + st.count++; + ids++; + } + did+=4; + } + result = func_search_entry(dbe, namespace, + search_entry, strlen(search_entry), W_SEARCH_ATTR_ALL, + del_trustee_set, &fs); + xfree(st.ids); + } + } + return(result); +} + +static int nw_get_trustee_set(int namespace, int searchattrib, + NW_HPATH *nwp, + uint32 *scansequence, + uint8 *oic) +{ + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); + if (result > -1) { + DIR_BASE_ENTRY *dbe=dir_base[result]; + char *unixname = alloc_nwpath2unix(&(dbe->nwpath), 2); + uint32 ids[20]; + int trustees[20]; + nwp_stat(&(dbe->nwpath), "nw_get_trustee_set"); + result=tru_get_trustee_set(dbe->nwpath.volume, unixname, + &(dbe->nwpath.statb), + (int)*scansequence, 20, ids, trustees); + if (result > 0) { + int k=-1; + while (++k < result){ + U32_TO_BE32(ids[k], oic); + oic += 4; + U16_TO_16(trustees[k], oic); + oic += 2; + } + (*scansequence)++; + } + xfree(unixname); + } + return(result); +} + + static int nw_get_full_path_cookies(int namespace, int destnamspace, NW_HPATH *nwp, int *cookieflags, @@ -1827,7 +2229,7 @@ static int nw_get_full_path_cookies(int namespace, /* SIMPLE IMPLEMENTATION, needs more work !!!! */ { - int result = build_base(namespace, nwp, nwp->pathes, 0, NULL); + int result = build_base(namespace, nwp, nwp->pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; uint8 *p = componentpath; @@ -1897,38 +2299,41 @@ static int nw_rename_file_dir(int namespace, int searchattrib, int renameflag) { - int result = build_base(namespace, nwps, pathes_s, 0, NULL); + int result = build_base(namespace, nwps, pathes_s, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe_s = dir_base[result]; uint8 last_part[258]; uint8 *unname_s= - (uint8*)nwpath_2_unix1(&(dbe_s->nwpath), 2, 1); - result = build_base(namespace, nwpd, pathes_d, 1, last_part); + (uint8*)alloc_nwpath2unix(&(dbe_s->nwpath), 2); + result = build_base(namespace, nwpd, pathes_d, 1, + last_part, sizeof(last_part)); if (result > -1) { DIR_BASE_ENTRY *dbe_d = dir_base[result]; - uint8 *unname_d = - (uint8*)nwpath_2_unix2(&(dbe_d->nwpath), 0, 1, last_part); + uint8 *unname_dp= /* directory */ + (uint8*)alloc_nwpath2unix(&(dbe_d->nwpath), 2); + uint8 *unname_d = + (uint8*)alloc_nwpath2unix_extra(&(dbe_d->nwpath), 0, last_part); - if (get_volume_options(dbe_s->nwpath.volume) & - VOL_OPTION_READONLY) result= EROFS; - else if (get_volume_options(dbe_d->nwpath.volume) & - VOL_OPTION_READONLY) result= EROFS; - - else { + if (tru_eff_rights_exists(dbe_s->nwpath.volume, unname_s, + &dbe_s->nwpath.statb, TRUSTEE_W|TRUSTEE_M|TRUSTEE_R)) + result=-0x8b; + else if (tru_eff_rights_exists(dbe_d->nwpath.volume, unname_dp, + &dbe_d->nwpath.statb, TRUSTEE_W)) + result=-0x8b; + + if (result > -1) { + seteuid(0); if (S_ISDIR(dbe_s->nwpath.statb.st_mode)) result = unx_mvdir(unname_s, unname_d); else result = unx_mvfile(unname_s, unname_d); + reseteuid(); + if (result==EEXIST) + result = -0x92; } XDPRINTF((5, 0, "Rename:%d '%s' -> '%s'", result, unname_s, unname_d)); + xfree(unname_dp); xfree(unname_d); - switch (result) { - case 0 : break; - - case EEXIST : result = -0x92; break; - case EROFS : result = -0x8b; break; - default : result = -0x8b; - } if (!result) { free_dbe_p(dbe_s); if ((result=get_add_new_entry(dbe_d, namespace, last_part, 0)) > -1) @@ -1945,15 +2350,41 @@ static int nw_modify_file_dir(int namespace, int searchattrib, uint32 infomask, DOS_MODIFY_INFO *dmi) { - int result = build_base(namespace, nwp, pathes, 0, NULL); + int result = build_base(namespace, nwp, pathes, 0, NULL, 0); if (result > -1) { DIR_BASE_ENTRY *dbe=dir_base[result]; - uint8 *uname=nwpath_2_unix1(&(dbe->nwpath), 2, 1); + uint8 *uname=alloc_nwpath2unix(&(dbe->nwpath), 2); struct stat *stb = &(dbe->nwpath.statb); + int voloptions = get_volume_options(dbe->nwpath.volume); if (-1 != (result=stat(uname, stb))){ + if (S_ISFIFO(stb->st_mode) || (voloptions&VOL_OPTION_IS_PIPE)){ + xfree(uname); + return(0); /* do nothing but report OK */ + } + if (tru_eff_rights_exists(dbe->nwpath.volume, uname, stb, + TRUSTEE_M)) + result=-0x8c; /* no modify rights */ + if (infomask & DOS_MSK_ATTRIBUTE){ + result=set_nw_attrib_dword(dbe->nwpath.volume, uname, stb, + GET_32(dmi->attributes)); + } + if ( (!result) && (infomask & DOS_MSK_INHERIT_RIGHTS) + && !tru_eff_rights_exists(dbe->nwpath.volume, uname, stb, TRUSTEE_A) ) { + int mask = tru_get_inherited_mask(dbe->nwpath.volume, uname, stb); + int grantmask = GET_16(dmi->rightsgrantmask); + int revokemask = GET_16(dmi->rightsrevokemask); + revokemask &= (~TRUSTEE_S); /* do not remove supervisory mask bit*/ + mask &= (~revokemask); + mask |= grantmask; + (void)tru_set_inherited_mask(dbe->nwpath.volume, uname, stb, + mask); + } + } else result=-0xff; + if (!result) { struct utimbuf ut; int do_utime=0; uint8 datetime[4]; + un_time_2_nw(stb->st_mtime, datetime, 1); un_date_2_nw(stb->st_mtime, datetime+2, 1); ut.actime = stb->st_atime; @@ -1966,7 +2397,6 @@ static int nw_modify_file_dir(int namespace, (int) *(datetime+3))); if (infomask & DOS_MSK_MODIFY_DATE || infomask & DOS_MSK_MODIFY_TIME) { -#if 1 if (infomask & DOS_MSK_MODIFY_TIME){ datetime[0] = dmi->modified_time[1]; datetime[1] = dmi->modified_time[0]; @@ -1976,11 +2406,9 @@ static int nw_modify_file_dir(int namespace, datetime[2] = dmi->modified_date[1]; datetime[3] = dmi->modified_date[0]; } -#endif do_utime++; } else if (infomask & DOS_MSK_CREAT_DATE || infomask & DOS_MSK_CREAT_TIME) { -#if 1 if (infomask & DOS_MSK_CREAT_TIME) { datetime[0] = dmi->created_time[1]; datetime[1] = dmi->created_time[0]; @@ -1989,7 +2417,6 @@ static int nw_modify_file_dir(int namespace, datetime[2] = dmi->created_date[1]; datetime[3] = dmi->created_date[0]; } -#endif do_utime++; } if (do_utime) { @@ -2000,10 +2427,13 @@ static int nw_modify_file_dir(int namespace, (int) *(datetime+3))); ut.modtime = nw_2_un_time(datetime+2, datetime); - utime(uname, &ut); + if (-1==utime(uname, &ut)) { + seteuid(0); + utime(uname, &ut); + reseteuid(); + } } - return(0); - } else result=-0xff; + } xfree(uname); } return(result); @@ -2099,6 +2529,29 @@ int handle_func_0x57(uint8 *p, uint8 *responsedata, int task) } break; + case 0x05 : /* Scan File/Dir for Trustees */ + { +#if 0 + int reserved = (int) *(p+1); +#endif + int searchattrib = (int) GET_16(p+2); /* LOW-HI */ + uint32 scansequence = GET_32(p+4); /* LOW-HI */ + NW_HPATH *nwpathstruct = (NW_HPATH *) (p+8); + result = nw_get_trustee_set(namespace, searchattrib, + nwpathstruct, + &scansequence, + responsedata+6); + U32_TO_32(scansequence, responsedata); + if (result > -1) { + U16_TO_16(result, responsedata+4); /* count */ + result=(result*6)+6; + } else { + U16_TO_16(0, responsedata+4); /* count */ + } + } + break; + + case 0x06 : /* Obtain File or Subdir Info */ { #if 0 @@ -2142,7 +2595,7 @@ static int code = 0; searchattrib, infomask, &dmi); } break; - + case 0x08 : /* Delete a File or Subdir */ { int searchattrib = (int) GET_16(p+2); /* LOW-HI */ @@ -2160,6 +2613,34 @@ static int code = 0; } break; + case 0x0a : /* Add trustee set to file or dir*/ + { + int searchattrib = (int) GET_16(p+2); /* LO-HI */ + int trustee_rights = (int) GET_16(p+4); /* LO-HI */ + /* if trustee_rights == 0xffff, use trustee from OIC structure */ + int count = (int) GET_16(p+6); /* LO-HI */ + NW_HPATH *nwp = (NW_HPATH *)(p+8); + if (trustee_rights==0xffff) trustee_rights=-1; + p+=315; + result = nw_add_trustee_set(namespace, searchattrib, nwp, + trustee_rights, + count, p); + /* OIC structure { uint8 id[4]; uint8 trusttee[2] LO-HI } */ + /* NO REPLY Packet */ + } + break; + + case 0x0b : /* delete trustee set from file or dir */ + { + int count = (int) GET_16(p+2); + NW_HPATH *nwp = (NW_HPATH *)(p+4); + p+=311; + result = nw_del_trustee_set(namespace, nwp, count, p); + /* object id's */ + /* NO REPLY Packet */ + } + break; + case 0x0c : /* alloc short dir Handle */ { int hmode = (int) GET_16(p+2); /* 0=p, 1=temp, 2=speztemp */ @@ -2223,7 +2704,7 @@ static int code = 0; case 0x15 : /* Get Path String from short dir new */ { int dir_handle=(int) *(p+1); - result=nw_get_directory_path(dir_handle, responsedata+1); + result=nw_get_directory_path(dir_handle, responsedata+1, 256); if (result > -1) { *responsedata=(uint8) result; result+=1; @@ -2248,25 +2729,28 @@ static int code = 0; } break; - case 0x18 : /* Get Name Spaces Loaded*/ + case 0x18 : /* Get Name Spaces Loaded */ { int volume=*(p+2); struct OUTPUT { - uint8 anz_name_spaces; + uint8 count_namespaces[2]; /* LO-HI */ uint8 name_space_list[1]; } *xdata= (struct OUTPUT*)responsedata; result=get_volume_options(volume); - xdata->anz_name_spaces = (uint8) 0; + xdata->count_namespaces[0] = (uint8) 0; + xdata->count_namespaces[1] = (uint8) 0; + if (result & VOL_NAMESPACE_DOS) - xdata->name_space_list[xdata->anz_name_spaces++] + xdata->name_space_list[xdata->count_namespaces[0]++] = (uint8) NAME_DOS; if (result & VOL_NAMESPACE_OS2) - xdata->name_space_list[xdata->anz_name_spaces++] + xdata->name_space_list[xdata->count_namespaces[0]++] = (uint8) NAME_OS2; if (result & VOL_NAMESPACE_NFS) - xdata->name_space_list[xdata->anz_name_spaces++] + xdata->name_space_list[xdata->count_namespaces[0]++] = (uint8) NAME_NFS; - result=xdata->anz_name_spaces+1; + + result = xdata->count_namespaces[0]+sizeof(xdata->count_namespaces); } break; @@ -2313,7 +2797,7 @@ static int code = 0; int searchattrib = (int) GET_16(p+2); /* LOW-HI */ uint32 infomask = GET_32(p+4); /* LOW-HI */ NW_HPATH *nwpathstruct = (NW_HPATH *) (p+8); - result = nw_get_eff_rights(namespace, nwpathstruct, + result = nsp_get_eff_rights(namespace, nwpathstruct, destnamspace, searchattrib, infomask, responsedata); @@ -2334,24 +2818,24 @@ int fill_namespace_buffer(int volume, uint8 *rdata) int count=0; *p++=5; /* we say 5 known namespaces (index 0=DOS .. 4=OS2 */ - + /* names */ *p++=3; memcpy(p,"DOS", 3); p+=3; *p++=9; memcpy(p,"MACINTOSH", 9); p+=9; *p++=3; memcpy(p,"NFS", 3); p+=3; *p++=4; memcpy(p,"FTAM", 4); p+=4; *p++=3; memcpy(p,"OS2", 3); p+=3; - + /* datastreams */ *p++=3; /* we say 3 datastreams here */ - - *p++=NAME_DOS; + + *p++=NAME_DOS; *p++=19; memcpy(p,"Primary Data Stream", 19); p+=19; - *p++=NAME_MAC; + *p++=NAME_MAC; *p++=23; memcpy(p,"Macintosh Resource Fork", 23); p+=23; - *p++=NAME_FTAM; + *p++=NAME_FTAM; *p++=20; memcpy(p,"FTAM Extra Data Fork", 20); p+=20; if (loaded_namespaces & VOL_NAMESPACE_DOS) ++count; @@ -2361,7 +2845,7 @@ int fill_namespace_buffer(int volume, uint8 *rdata) if (loaded_namespaces & VOL_NAMESPACE_DOS) *p++ = NAME_DOS; if (loaded_namespaces & VOL_NAMESPACE_OS2) *p++ = NAME_OS2; if (loaded_namespaces & VOL_NAMESPACE_NFS) *p++ = NAME_NFS; - + count=0; if (voloptions & VOL_NAMESPACE_DOS) ++count; if (voloptions & VOL_NAMESPACE_OS2) ++count; @@ -2386,21 +2870,24 @@ int get_namespace_dir_entry(int volume, uint32 basehandle, DIR_BASE_ENTRY *e = dir_base[result]; NW_SCAN_DIR_INFO *scif = (NW_SCAN_DIR_INFO*)rdata; uint8 fname[20]; - (void) nwp_stat(&(e->nwpath), "get_namespace_dir_entry"); + char *unixname=alloc_nwpath2unix(&(e->nwpath), 2); + (void) stat(unixname, &(e->nwpath.statb)); + memset(rdata, 0, sizeof(NW_SCAN_DIR_INFO)); #if 0 U32_TO_32(basehandle, scif->searchsequence); #else U32_TO_32(name_2_base(&(e->nwpath), NAME_DOS, 1), scif->searchsequence); #endif - (void)build_dos_name(e, fname); + (void)build_dos_name(e, fname, sizeof(fname)); if (S_ISDIR(e->nwpath.statb.st_mode)) { get_dos_dir_attrib(&(scif->u.d), &e->nwpath.statb, - e->nwpath.volume, fname); + e->nwpath.volume, fname, unixname); } else { get_dos_file_attrib(&(scif->u.f), &e->nwpath.statb, - e->nwpath.volume, fname); + e->nwpath.volume, fname, unixname); } + xfree(unixname); return(sizeof(NW_SCAN_DIR_INFO)); } return(result); @@ -2494,7 +2981,7 @@ void init_name_space_module(int max_baseh, int max_searchh) max_dir_base_entries=(max_baseh < 5) ? MAX_DIR_BASE_ENTRIES : max_baseh; dir_base=(DIR_BASE_ENTRY **)xcmalloc( sizeof(DIR_BASE_ENTRY*) * max_dir_base_entries); - + max_dir_search_handles=(max_searchh < 10 || max_searchh > 255) ? 50 : max_searchh; dir_search_handles=(DIR_SEARCH_HANDLE **)xcmalloc( sizeof(DIR_SEARCH_HANDLE*) * max_dir_search_handles); diff --git a/ncpserv.c b/ncpserv.c index b011e2f..6adf2b5 100644 --- a/ncpserv.c +++ b/ncpserv.c @@ -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); diff --git a/net.h b/net.h index 15d91de..48185b2 100644 --- a/net.h +++ b/net.h @@ -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 #include #include +#include /* moved 12-May-98 0.99.pl9 */ + #include +#ifdef __USE_BSD +# undef signal +# define signal sysv_signal +#endif #include #ifndef LINUX @@ -31,9 +42,12 @@ #endif #include -#include +/* #include moved 12-May-98 0.99.pl9 */ #include #include +#ifndef S_ISLNK +# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif #include #include #include @@ -50,7 +64,6 @@ extern int errno; /* # include "common.h" */ /* # include "portable.h" , needed ??? */ # include - #else # include # 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; diff --git a/net1.c b/net1.c index fa3f6c1..1fef33b 100644 --- a/net1.c +++ b/net1.c @@ -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); +} + + + + diff --git a/net1.h b/net1.h index cd999a1..69a0288 100644 --- a/net1.h +++ b/net1.h @@ -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 diff --git a/nwattrib.c b/nwattrib.c index 2d23ae5..4c24bdd 100644 --- a/nwattrib.c +++ b/nwattrib.c @@ -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 #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) @@ -31,7 +33,7 @@ static void put_attr_to_disk(int dev, ino_t inode, uint32 attrib) int l; uint8 buf_uc[4]; U32_TO_BE32(inode, buf_uc); - l=sprintf(buf, "%s/%x/%x/%x/%x", path_attributes, + l=sprintf(buf, "%s/%x/%x/%x/%x", path_attributes, dev, (int) buf_uc[0], (int) buf_uc[1], @@ -40,7 +42,7 @@ static void put_attr_to_disk(int dev, ino_t inode, uint32 attrib) unx_xmkdir(buf, 0755); sprintf(buf+l, "/%x", (int) buf_uc[3]); unlink(buf); - l=sprintf(battrib, "%08x", (unsigned int) attrib); + l=sprintf(battrib, "%08x", (unsigned int) attrib); symlink(battrib, buf); reseteuid(); } @@ -50,7 +52,7 @@ static void free_attr_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", path_attributes, + sprintf(buf, "%s/%x/%x/%x/%x/%x", path_attributes, dev, (int) buf_uc[0], (int) buf_uc[1], @@ -78,252 +80,162 @@ static int get_attr_from_disk(int dev, ino_t inode, uint32 *attrib) seteuid(0); l=readlink(buf, battrib, 224); reseteuid(); - if (l > 0) { + if (l > 0) { unsigned int uattrib=0; battrib[l]='\0'; if (1 == sscanf(battrib, "%x", &uattrib)) { *attrib = uattrib; 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; + 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); - } else { - if (is_dir) - attrib = FILE_ATTR_DIR; - else - attrib = FILE_ATTR_A; /* default archive flag */ + } + + if (voloptions & VOL_OPTION_READONLY){ + attrib |= (FILE_ATTR_DELETE_INH|FILE_ATTR_RENAME_INH|FILE_ATTR_R); } - if (act_uid) { - /* if not root */ - int acc=get_real_access(stb); - if (!(acc & W_OK)) { - attrib |= FILE_ATTR_R; /* RO */ - } - if (!(acc & R_OK)) { - attrib |= FILE_ATTR_H; /* We say hidden here */ + if (!(voloptions & VOL_OPTION_ATTRIBUTES)) { + /* only for volumes without attribute handling */ + if (act_uid) { + /* if not root */ + int acc=get_unix_eff_rights(stb); + if (!(acc & W_OK)) { + attrib |= FILE_ATTR_R; /* RO */ + } + if (!(acc & R_OK)) { + 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) + uint32 oldattrib,newattrib; + int voloptions=get_volume_options(volume); + if (voloptions & VOL_OPTION_IS_PIPE) + 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_IS_PIPE) - return(0); - - if (!(get_real_access(stb) & W_OK)) - return(-0x8c); /* no modify rights */ - - if (is_dir) attrib |= 0x10; - else attrib &= ~0x10; - put_attr_to_disk(stb->st_dev, stb->st_ino, attrib); - return(0); -} - -int set_nw_attrib_byte(struct stat *stb, int voloptions, int battrib) -{ - 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); -} - -void set_nw_archive_bit(int dev, ino_t inode) -/* only called for files */ -{ - uint32 attrib; - 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++; - } - } - } - } + 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 */ } } - *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); + 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 ((!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_trustee(int dev, ino_t inode, uint32 id, int trustee) +int set_nw_attrib_dword(int volume, char *unixname, struct stat *stb, uint32 attrib) +/* wattrib = ext_attrib, attrib */ { - return(0); - -#if 0 - if (get_own_trustee(dev, inode, TRUSTEE_M) & (TRUSTEE_M | TRUSTEE_S)){ - - } else return(-0x8c); /* no modify privileges */ -#endif + return(set_nw_attrib(volume,unixname,stb,attrib, 0)); } +int set_nw_attrib_byte(int volume, char *unixname, struct stat *stb, int battrib) +{ + return(set_nw_attrib(volume,unixname,stb,(uint32)battrib, 1)); +} -void free_nw_ext_inode(int dev, ino_t inode) +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); + } + } +} + +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 */ { - free_attr_from_disk(dev, inode); - free_trustees_from_disk(dev, inode); + int voloptions=get_volume_options(volume); + if (voloptions & VOL_OPTION_ATTRIBUTES) + free_attr_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); + } } + diff --git a/nwattrib.h b/nwattrib.h index 0e24a85..7dcf8a0 100644 --- a/nwattrib.h +++ b/nwattrib.h @@ -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 diff --git a/nwbind.c b/nwbind.c index 1ccce39..f0dbe47 100644 --- a/nwbind.c +++ b/nwbind.c @@ -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" @@ -49,7 +58,7 @@ static void write_to_nwserv(int what, int connection, int mode, switch (what) { case 0x4444 : /* tell the wdog there's no need to look 0 */ /* activate wdogs to free connection 1 */ - /* the connection ist closed 99 */ + /* the connection ist closed 99 */ write(FD_NWSERV, &what, sizeof(int)); write(FD_NWSERV, &connection, sizeof(int)); write(FD_NWSERV, &mode, sizeof(int)); @@ -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)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;i0 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) { @@ -324,17 +591,17 @@ static void handle_fxx(int gelen, int func) uint32 id = GET_BE32(rdata+1); internal_act=1; if (get_guid((int*) responsedata, (int*)(responsedata+sizeof(int)), - id, (char *) NULL) != 0) { - completition = 0xff; + id, (char *) NULL) != 0) { + completition = 0xff; XDPRINTF((2, 0, "quota id-uid mapping failure %d 0x%x", ufunc, id)); } internal_act=0; /* OK if supervisor or trying to read (0x29) own limits */ - if (act_c->object_id == 1 || - (act_c->object_id == id && ufunc == 0x29)) - ((int *) responsedata)[2] = 0; /* OK */ + if ( (act_c->id_flags&1) || + (act_c->object_id == id && ufunc == 0x29)) + ((int *) responsedata)[2] = 0; /* OK */ else - ((int *) responsedata)[2] = 1; /* Fail */ + ((int *) responsedata)[2] = 1; /* Fail */ data_len = sizeof(int)*3; } break; @@ -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,8 +1300,8 @@ 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 - : (uint8) 0x22; + *xdata = (act_c->id_flags&1) ? (uint8) 0x33 + : (uint8) 0x22; U32_TO_BE32(act_c->object_id, (xdata+1)); } data_len = 5; @@ -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; @@ -1108,19 +1374,19 @@ static void handle_fxx(int gelen, int func) /* from Guntram Blohm */ p += (*p+1); /* here is crypted password length */ if (0 == (result = find_obj_id(&obj))) { - internal_act=1; + internal_act=1; if (obj.id != 1) 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); + result=nw_keychange_passwd(obj.id, act_c->crypt_key, + rdata, (int)*p, p+1, act_c->id_flags); if (!result) test_ins_unx_user(obj.id); - internal_act = 0; - } + 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; @@ -1257,9 +1539,9 @@ static void handle_fxx(int gelen, int func) case 0x69: /* close file and start queue old ?? */ case 0x7f: { /* close file and start queue */ uint32 q_id = GET_BE32(rdata); - uint32 job_id = (ufunc==0x69) - ? GET_BE16(rdata+4) - : GET_BE16(rdata+4); + uint32 job_id = (ufunc==0x69) + ? GET_BE16(rdata+4) + : GET_BE16(rdata+4); int result = nw_close_queue_job(q_id, job_id, responsedata); if (result > -1) @@ -1299,9 +1581,9 @@ static void handle_fxx(int gelen, int func) case 0x87: /* Get Queue Job File Size */ { uint32 q_id = GET_BE32(rdata); - uint32 job_id = (ufunc==0x78) - ? GET_BE16(rdata+4) - : GET_BE16(rdata+4); + uint32 job_id = (ufunc==0x78) + ? GET_BE16(rdata+4) + : GET_BE16(rdata+4); int result = nw_get_queue_job_file_size(q_id, job_id); if (result > -1) { uint8 *p=responsedata; @@ -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,22 +1671,26 @@ 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 job_list[4]; /* this is repeated */ + 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)*/ case 0x83: { /* finish servicing queue job */ uint32 q_id = GET_BE32(rdata); - uint32 job_id = GET_BE16(rdata+4); + uint32 job_id = GET_BE16(rdata+4); #if 0 uint32 chargeinfo = GET_BE32(rdata+8); #endif @@ -1408,7 +1705,7 @@ static void handle_fxx(int gelen, int func) case 0x73: /* abort servicing queue job (old) */ case 0x84: { /* abort servicing queue job */ uint32 q_id = GET_BE32(rdata); - uint32 job_id = GET_BE16(rdata+4); + uint32 job_id = GET_BE16(rdata+4); int result = nw_finish_abort_queue_job(1, act_c->object_id, act_connection, @@ -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); diff --git a/nwbind.h b/nwbind.h index e568382..176c284 100644 --- a/nwbind.h +++ b/nwbind.h @@ -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; diff --git a/nwconn.c b/nwconn.c index 9f3b4b5..fa3b125 100644 --- a/nwconn.c +++ b/nwconn.c @@ -1,7 +1,7 @@ -/* nwconn.c 18-Nov-97 */ +/* nwconn.c 18-Apr-00 */ /* one process / connection */ -/* (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 @@ -18,6 +18,13 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* history since 21-Apr-00 + * + * mst:25-Apr-00: added routines for sending nwconn data to nwbind + * + */ + + #include "net.h" #if 1 # define LOC_RW_BUFFERSIZE RW_BUFFERSIZE @@ -30,9 +37,9 @@ #include "connect.h" #include "nwqconn.h" #include "namspace.h" +#include "nwshare.h" #include "nwconn.h" -int act_connection = 0; int act_pid = 0; #define FD_NCP_OUT 3 @@ -211,6 +218,57 @@ static void pr_debug_request() #if TEST_FNAME static int test_handle = -1; #endif + +static void handle_nwbind_request(void) /* mst:25-Apr-00 */ +{ + int result = 0; + char buf[IPX_MAX_DATA]; + char *data = &(buf[sizeof(NCPRESPONSE)]); + int data_len = 0; + + switch (ncprequest->function) { + case 0x1: { /* get number and handles of open files */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 offset[4]; /* handle offset */ + } *input = (struct INPUT *) (ncprequest); + struct XDATA { + uint8 count_handles[4]; + uint8 handles[4]; + } *xdata = (struct XDATA*) data; + int handles = nw_get_count_open_files(xdata->handles, GET_BE32(input->offset)); + U32_TO_BE32(handles, xdata->count_handles); + data_len = (handles+1) * 4; + } + break; + + default : + result = 0xfb; + } + + { + NCPRESPONSE *resp = (NCPRESPONSE*)&buf; + ipxAddr_t to_addr; + memcpy(&to_addr, &my_addr, sizeof(ipxAddr_t)); + U16_TO_BE16(sock_nwbind, to_addr.sock); + ud.addr.buf = (char*)&to_addr; + + resp->type[0] = resp->type[1]=0x32; + resp->sequence = ncprequest->sequence; + resp->connection = ncprequest->connection; + resp->task = ncprequest->task; + resp->high_connection = ncprequest->high_connection; + resp->completition = result; + resp->connect_status = 0; + ud.udata.len = ud.udata.maxlen = sizeof(NCPRESPONSE) + data_len; + ud.udata.buf = (char*)resp; + XDPRINTF((3, 0, "send reply to nwbind")); + result = t_sndudata(FD_NCP_OUT, &ud); + ud.addr.buf = (char*)&from_addr; + ud.udata.buf = (char*)&ipxdata; + } +} + static int handle_ncp_serv(void) { int function = (int)ncprequest->function; @@ -221,10 +279,10 @@ static int handle_ncp_serv(void) if (last_sequence == (int)ncprequest->sequence && ncp_type != 0x1111){ /* send the same again */ - if (t_sndudata(FD_NCP_OUT, &ud) < 0){ + if (t_sndudata(FD_NCP_OUT, &ud) < 0) { if (nw_debug) t_error("t_sndudata !OK"); } - XDPRINTF((2,0, "Sequence %d is written twice", (int)ncprequest->sequence)); + XDPRINTF((3,0, "Sequence %d is written twice", (int)ncprequest->sequence)); return(0); } req_printed=0; @@ -241,1534 +299,1872 @@ static int handle_ncp_serv(void) if (nw_debug > 5) pr_debug_request(); if (ncp_type == 0x2222) { + switch (function) { + + /* 0.99.pl18, 25-Sep-99 + * these log/lock functions are not well tested and perhaps not + * ok . + */ + case 0x3 : { /* Log File */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dir_handle; + uint8 lock_flag; /* 0 = log, 1 = lock excl */ + /* 3 = lock shared */ + uint8 timeout[2]; /* HI LO */ + uint8 len; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_log_file( input->lock_flag, + GET_BE16(input->timeout), + input->dir_handle, + input->len, + input->path); + if (result) completition = (uint8) -result; + } + break; #if 0 - case 0x3 : { /* Log File */ -NWCONN 1:UNKNOWN FUNCTION od. TYPE: 0x3 -NWCONN 1:NWCONN NCP_RESP seq:56, conn:1, compl=0xfb task=5 TO - net=0:0:0:22, node=0:0:1:22:59:52, sock=40:03 -NWCONN 1:NCP REQUEST: func=0x03, ufunc=0x00, seq:060, task:05 -NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', - '9','7','.','Z','I','P' - ;; - } break; - case 0x4 : { /* Lock File Set */ - ;; - } break; - case 0x5 : { /* Release File */ - ;; - } break; - case 0x6 : { /* Release File Set */ - ;; - } break; - case 0x7 : { /* Clear File */ - ;; - } break; - case 0x8 : { /* Clear File Set */ - ;; - } break; + case 0x4 : { /* Lock File Set */ + + } + break; #endif + + case 0x5 : /* Release File */ + case 0x7 : { /* Clear File, removes file from logset */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dir_handle; + uint8 len; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_log_file( (function==0x7) + ? -2 /* unlock and unlog */ + : -1, /* unlock */ + 0, + input->dir_handle, + input->len, + input->path); + if (result) completition = (uint8) -result; + } + break; - case 0x12 : { /* Get Volume Info with Number */ - int volume = (int)*requestdata; - struct XDATA { - uint8 sec_per_block[2]; - uint8 total_blocks[2]; - uint8 avail_blocks[2]; - uint8 total_dirs[2]; - uint8 avail_dirs[2]; - uint8 name[16]; - uint8 removable[2]; - } *xdata = (struct XDATA*) responsedata; - int result; - memset(xdata, 0, sizeof(struct XDATA)); - if ((result = nw_get_volume_name(volume, xdata->name))>-1){ - struct fs_usage fsp; - if (!nw_get_fs_usage(xdata->name, &fsp, - entry8_flags&0x40 )) { - int sector_scale=1; - while (fsp.fsu_blocks/sector_scale > 0xffff) - sector_scale+=2; - U16_TO_BE16(sector_scale, xdata->sec_per_block); - U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks); - U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks); - U16_TO_BE16(fsp.fsu_files, xdata->total_dirs); - U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs); - if ( get_volume_options(volume) & VOL_OPTION_REMOUNT) { - U16_TO_BE16(1, xdata->removable); - } else { - U16_TO_BE16(0, xdata->removable); - } + case 0x6 : /* Release File Set */ + case 0x8 : { /* Clear File Set */ + int result = share_handle_lock_sets( + 1, /* File Set */ + (function==0x8) + ? -2 /* Clear */ + : -1, /* Release */ + 0); + + if (result) completition = (uint8) -result; + } + break; + + case 0x9 : { /* Log Logical Record */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 lock_flag; /* 0 = log */ + /* 1 = exclusive lock */ + /* 3 = shared ro lock */ + uint8 timeout[2]; /* HI LO */ + uint8 len; /* synch name len */ + uint8 name[2]; /* synch name */ + } *input = (struct INPUT *) (ncprequest); + int result = nw_log_logical_record( + (int) input->lock_flag, + (int) GET_BE16(input->timeout), + (int) input->len, + input->name); + if (result) completition = (uint8) -result; + } + break; + + case 0xa : { /* Log Logical Record Set */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 lock_flag; /* 0 = log */ + /* 1 = exclusive lock */ + /* 3 = shared ro lock */ + uint8 timeout[2]; /* HI LO */ + } *input = (struct INPUT *) (ncprequest); + int result = share_handle_lock_sets( + 2, /* Logical Record Set */ + (int) input->lock_flag, + (int) GET_BE16(input->timeout) ); + if (result) completition = (uint8) -result; + } + break; + + case 0xb : /* Clear Logical Record ?? */ + /* case 0xc :*/ { /* Release Logical Record ?? */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 len; /* synch name len */ + uint8 name[2]; /* synch name */ + } *input = (struct INPUT *) (ncprequest); + int result = nw_log_logical_record( + (function == 0xb) + ? -2 /* unlock + unlog */ + : -1, /* unlock */ + 0, + (int) input->len, + input->name); + if (result) completition = (uint8) -result; + } + break; + + case 0xe : /* Clear Logical Record Set */ + case 0xd : { /* Release Logical Record Set */ + int result = share_handle_lock_sets( + 2, /* Logical Record Set */ + (function==0xe) + ? -2 /* Clear */ + : -1, /* Release */ + 0); + if (result) completition = (uint8) -result; + } + break; + + case 0x12 : { /* Get Volume Info with Number */ + int volume = (int)*requestdata; + struct XDATA { + uint8 sec_per_block[2]; + uint8 total_blocks[2]; + uint8 avail_blocks[2]; + uint8 total_dirs[2]; + uint8 avail_dirs[2]; + uint8 name[16]; + uint8 removable[2]; + } *xdata = (struct XDATA*) responsedata; + int result; + memset(xdata, 0, sizeof(struct XDATA)); + if ((result = nw_get_volume_name(volume, xdata->name, sizeof(xdata->name)))>-1){ + struct fs_usage fsp; + if (!nw_get_fs_usage(xdata->name, &fsp, + entry8_flags&0x40 )) { + int sector_scale=1; + while (fsp.fsu_blocks/sector_scale > 0xffff) + sector_scale+=2; + U16_TO_BE16(sector_scale, xdata->sec_per_block); + U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks); + U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks); + U16_TO_BE16(fsp.fsu_files, xdata->total_dirs); + U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs); + if ( get_volume_options(volume) & VOL_OPTION_REMOUNT) { + U16_TO_BE16(1, xdata->removable); + } else { + U16_TO_BE16(0, xdata->removable); + } + } + data_len = sizeof(struct XDATA); + } else completition = (uint8) -result; + } + break; + + case 0x13 : { /* Get connection ?? */ + /* TODO !!!!!!! */ + *responsedata=(uint8) act_connection; + data_len = 1; + } + break; + + case 0x14 : { /* GET DATE und TIME */ + struct SERVER_DATE { + uint8 year; + uint8 mon; + uint8 day; + uint8 std; + uint8 min; + uint8 sec; + uint8 day_of_week; + } *mydate = (struct SERVER_DATE*) responsedata; + struct tm *s_tm; + time_t timer; + time(&timer); + s_tm = localtime(&timer); + mydate->year = (uint8) s_tm->tm_year; + mydate->mon = (uint8) s_tm->tm_mon+1; + mydate->day = (uint8) s_tm->tm_mday; + + mydate->std = (uint8) s_tm->tm_hour; + mydate->min = (uint8) s_tm->tm_min; + mydate->sec = (uint8) s_tm->tm_sec; + mydate->day_of_week = (uint8) s_tm->tm_wday; /* Wochentag */ + data_len = sizeof(struct SERVER_DATE); + } + break; + + case 0x15 : + return(-1); /* nwbind must do this call */ + + case 0x16 : { + /* uint8 len = *(requestdata+1); */ + uint8 *p = requestdata +2; + + switch (*p) { + + case 0 : { + /******** SetDirektoryHandle *************/ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 target_dir_handle; /* to change */ + uint8 source_dir_handle; + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + completition = + (uint8)-nw_set_dir_handle((int)input->target_dir_handle, + (int)input->source_dir_handle, + input->path, + (int)input->pathlen, + (int)(ncprequest->task)); + } + break; + + case 0x1 : { + /******** GetDirektoryPATH ***************/ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; + } *input = (struct INPUT *) (ncprequest); + struct XDATA { + uint8 len; + uint8 name[256]; + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_directory_path((int)input->dir_handle, + xdata->name, sizeof(xdata->name)); + if (result > -1){ + xdata->len = (uint8) result; + data_len = result + 1; + xdata->name[result] = '\0'; + XDPRINTF((5,0, "GetDirektoryPATH=%s", xdata->name)); + } else completition = (uint8)-result; + } + break; + + case 0x2 : { /* Scan Direktory Information */ + /******** Scan Dir Info ****************/ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Verzeichnis Handle */ + uint8 sub_dir_nmbr[2]; /* HI LOW */ + /* firsttime 1 */ + uint8 len; /* kann auch 0 sein */ + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + struct XDATA { + uint8 sub_dir_name[16]; + uint8 create_date_time[4]; + uint8 owner_id[4]; /* HI LOW */ + uint8 max_right_mask; /* inherited right mask */ + uint8 reserved; /* Reserved by Novell */ + uint8 sub_dir_nmbr[2]; /* HI LOW */ + } *xdata = (struct XDATA*) responsedata; + int result; + memcpy(xdata->sub_dir_nmbr, input->sub_dir_nmbr, 2); + result = nw_scan_dir_info((int)input->dir_handle, + input->path, (int)input->len, + xdata->sub_dir_nmbr, xdata->sub_dir_name, + xdata->create_date_time, xdata->owner_id); + if (result > -1){ + xdata->max_right_mask = (uint8)result; + data_len = sizeof(struct XDATA); + XDPRINTF((5,0,"Scan Dir Info max_right_mask=%d", (int)result)); + } else completition = (uint8)-result; + } + break; + + case 0x3 : { /* Get Direktory Rights */ + /******** Get Eff Dir Rights ****************/ + struct XDATA { + uint8 eff_right_mask; /* Effektive Right to Dir, old! */ + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_eff_dir_rights( + (int)*(p+1), + p+3, + (int)*(p+2), 0); + if (result > -1) { + xdata->eff_right_mask = (uint8) result; + data_len = 1; + XDPRINTF((5,0,"Got eff Dir Rights=%d", (int)result)); + } else completition = (uint8) -result; + } + break; + + case 0x4 : { /* Modify Max Right MAsk */ + /******** MODIFY MAX RIGHT MASK ****************/ + /* NO REPLY !! */ + completition = 0xfb; /* TODO */ + } + break; + + case 0x5 : { /* Get Volume Number 0 .. 31 */ + /******** GetVolume Number ***************/ + /* p+1 = namelen */ + /* p+2 = data z.b 'SYS' */ + struct XDATA { + uint8 volume; /* Nummer */ + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_volume_number(p+2, (int)*(p+1)); + if (result > -1) { + xdata->volume = (uint8) result; + data_len = 1; + } else completition = (uint8) -result; + } + break; + + case 0x6 : { /* Get Volume Name from 0 .. 31 */ + /******** Get Volume Name ***************/ + struct XDATA { + uint8 namelen; + uint8 name[16]; + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_volume_name((int)*(p+1), + xdata->name, sizeof(xdata->name)); + if (result > -1) { + xdata->namelen = (uint8) result; + data_len = result+1; + } else completition = (uint8) -result; + } + break; + + case 0xa : { /* create directory */ + /******** Create Dir *********************/ + int dir_handle = (int) *(p+1); +#if 0 + int rightmask = (int) *(p+2); +#endif + int pathlen = (int) *(p+3); + uint8 *path = p+4; + int code = nw_mk_rd_dir(dir_handle, path, pathlen, 1); + if (code) completition = (uint8) -code; + } + break; + + case 0xb : { /* delete dirrctory */ + /******** Delete DIR *********************/ + int dir_handle = (int) *(p+1); +#if 0 + int reserved = (int) *(p+2); /* Res. by NOVELL */ +#endif + int pathlen = (int) *(p+3); + uint8 *path = p+4; + int code = nw_mk_rd_dir(dir_handle, path, pathlen, 0); + if (code) completition = (uint8) -code; + } + break; + + case 0xd : { /* Add Trustees to DIR */ + /******** AddTrustesstoDir ***************/ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Verzeichnis Handle */ + uint8 trustee_id[4]; /* Trustee Object ID */ + uint8 trustee_right_mask; + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_add_trustee( + input->dir_handle, + input->path, input->pathlen, + GET_BE32(input->trustee_id), + (int)input->trustee_right_mask, + 0); + if (result) completition = (uint8) -result; + } + break; + + case 0xe : { /* remove trustees */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Handle */ + uint8 trustee_id[4]; /* Trustee Object ID */ + uint8 reserved; + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_del_trustee( + input->dir_handle, + input->path, input->pathlen, + GET_BE32(input->trustee_id), + 0); /* normal */ + if (result) completition = (uint8) -result; + } + break; + + case 0xf : { /* rename dir */ + /******** Rename DIR *********************/ + int dir_handle = (int) *(p+1); + int oldpathlen = (int) *(p+2); + uint8 *oldpath = p+3; + int newpathlen = (int) *(oldpath + oldpathlen); + uint8 *newpath = oldpath + oldpathlen + 1; + int code = mv_dir(dir_handle, + oldpath, oldpathlen, + newpath, newpathlen); + if (code) completition = (uint8) -code; + } + break; + + case 0x12 : /* Allocate Permanent Dir Handle */ + /******** Allocate Permanent DIR Handle **/ + case 0x13 : /* Allocate Temp Dir Handle */ + /******** Allocate Temp DIR Handle **/ + case 0x16 : { /* Allocate Special Temp Dir Handle */ + /******** Allocate spez temp DIR Handle **/ + + struct XDATA { + uint8 dirhandle; /* new Dir Handle */ + uint8 right_mask; /* 0xff effektive Right MAsk ? */ + } *xdata = (struct XDATA*) responsedata; + int eff_rights; + int dirhandle = nw_alloc_dir_handle( + (int) *(p+1), + p+4, + (int)*(p+3), + (int)*(p+2), + (*p==0x12) ? 0 + : ((*p==0x13) ? 1 : 2), + (int)(ncprequest->task), + &eff_rights); + if (dirhandle > -1){ + xdata->dirhandle = (uint8) dirhandle; + xdata->right_mask = eff_rights; + data_len = sizeof(struct XDATA); + } else completition = (uint8) -dirhandle; + + } + break; + + case 0x14 : { /* deallocate Dir Handle */ + /******** Free DIR Handle ****************/ + int err_code = nw_free_dir_handle((int)*(p+1), + (int)(ncprequest->task)); + if (err_code) completition = (uint8) -err_code; + } + break; + + case 0x15 : { /* liefert Volume Information */ + /******** Get Volume Info with Handle ****/ + struct XDATA { + uint8 sectors[2]; + uint8 total_blocks[2]; + uint8 avail_blocks[2]; + uint8 total_dirs[2]; /* anz dirs */ + uint8 avail_dirs[2]; /* free dirs */ + uint8 name[16]; /* SYS Name */ + uint8 removable[2]; + } *xdata = (struct XDATA*)responsedata; + int result = nw_get_vol_number((int)*(p+1)); + memset(xdata, 0, sizeof(struct XDATA)); + if (result > -1) { + int volume = result; + result = nw_get_volume_name(volume, + xdata->name, sizeof(xdata->name) ); + if (result > -1) { + struct fs_usage fsp; + if (!nw_get_fs_usage(xdata->name, &fsp, + entry8_flags&0x40 )) { + int sector_scale=1; + while (fsp.fsu_blocks/sector_scale > 0xffff) + sector_scale+=2; + U16_TO_BE16(sector_scale, xdata->sectors); + U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks); + U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks); + U16_TO_BE16(fsp.fsu_files, xdata->total_dirs); + U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs); + if (get_volume_options(volume) & VOL_OPTION_REMOUNT) { + U16_TO_BE16(1, xdata->removable); + } else { + U16_TO_BE16(0, xdata->removable); } - data_len = sizeof(struct XDATA); - } else completition = (uint8) -result; - } break; - - case 0x13 : { /* Get connection ?? */ - /* TODO !!!!!!! */ - *responsedata=(uint8) act_connection; - data_len = 1; - } break; - - case 0x14 : { /* GET DATE und TIME */ - struct SERVER_DATE { - uint8 year; - uint8 mon; - uint8 day; - uint8 std; - uint8 min; - uint8 sec; - uint8 day_of_week; - } *mydate = (struct SERVER_DATE*) responsedata; - struct tm *s_tm; - time_t timer; - time(&timer); - s_tm = localtime(&timer); - mydate->year = (uint8) s_tm->tm_year; - mydate->mon = (uint8) s_tm->tm_mon+1; - mydate->day = (uint8) s_tm->tm_mday; - - mydate->std = (uint8) s_tm->tm_hour; - mydate->min = (uint8) s_tm->tm_min; - mydate->sec = (uint8) s_tm->tm_sec; - mydate->day_of_week = (uint8) s_tm->tm_wday; /* Wochentag */ - data_len = sizeof(struct SERVER_DATE); + } + data_len = sizeof(struct XDATA); + XDPRINTF((5,0,"GIVE VOLUME INFO from :%s:", xdata->name)); + result = 0; } - break; + } + completition = (uint8)-result; + } + break; - case 0x15 : - return(-1); /* nwbind must do this call */ - - - case 0x16 : { - /* uint8 len = *(requestdata+1); */ - uint8 *p = requestdata +2; - if (0 == *p){ - /******** SetDirektoryHandle *************/ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 target_dir_handle; /* to change */ - uint8 source_dir_handle; - uint8 pathlen; - uint8 path[2]; - } *input = (struct INPUT *) (ncprequest); - completition = - (uint8)-nw_set_dir_handle((int)input->target_dir_handle, - (int)input->source_dir_handle, - input->path, - (int)input->pathlen, - (int)(ncprequest->task)); - - } else if (1 == *p){ - /******** GetDirektoryPATH ***************/ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; - } *input = (struct INPUT *) (ncprequest); - struct XDATA { - uint8 len; - uint8 name[256]; - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_directory_path((int)input->dir_handle, xdata->name); - if (result > -1){ - xdata->len = (uint8) result; - data_len = result + 1; - xdata->name[result] = '\0'; - XDPRINTF((5,0, "GetDirektoryPATH=%s", xdata->name)); - } else completition = (uint8)-result; - } else if (2 == *p){ /* Scan Direktory Information */ - /******** Scan Dir Info ****************/ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* Verzeichnis Handle */ - uint8 sub_dir_nmbr[2]; /* HI LOW */ - /* firsttime 1 */ - uint8 len; /* kann auch 0 sein */ - uint8 path[2]; - } *input = (struct INPUT *) (ncprequest); - struct XDATA { - uint8 sub_dir_name[16]; - uint8 create_date_time[4]; - uint8 owner_id[4]; /* HI LOW */ - uint8 max_right_mask; - uint8 reserved; /* Reserved by Novell */ - uint8 sub_dir_nmbr[2]; /* HI LOW */ - } *xdata = (struct XDATA*) responsedata; - int result; - memcpy(xdata->sub_dir_nmbr, input->sub_dir_nmbr, 2); - result = nw_scan_dir_info((int)input->dir_handle, - input->path, (int)input->len, - xdata->sub_dir_nmbr, xdata->sub_dir_name, - xdata->create_date_time, xdata->owner_id); - if (result > -1){ - xdata->max_right_mask = (uint8)result; - data_len = sizeof(struct XDATA); - XDPRINTF((5,0,"Scan Dir Info max_right_mask=%d", (int)result)); - } else completition = (uint8)-result; - } else if (*p == 0x3){ /* Get Direktory Rights */ - /******** Get Eff Dir Rights ****************/ - struct XDATA { - uint8 eff_right_mask; /* Effektive Right to Dir, old! */ - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_eff_dir_rights( - (int)*(p+1), - p+3, - (int)*(p+2), 0); - if (result > -1) { - xdata->eff_right_mask = (uint8) result; - data_len = 1; - XDPRINTF((5,0,"Got eff Dir Rights=%d", (int)result)); - } else completition = (uint8) -result; - } else if (*p == 0x4){ /* Modify Max Right MAsk */ - /******** MODIFY MAX RIGHT MASK ****************/ - /* NO REPLY !! */ - completition = 0xfb; /* TODO */ - } else if (*p == 0x5){ /* Get Volume Number 0 .. 31 */ - /******** GetVolume Number ***************/ - /* p+1 = namelen */ - /* p+2 = data z.b 'SYS' */ - struct XDATA { - uint8 volume; /* Nummer */ - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_volume_number(p+2, (int)*(p+1)); - if (result > -1) { - xdata->volume = (uint8) result; - data_len = 1; - } else completition = (uint8) -result; - } else if (*p == 0x6){ /* Get Volume Name from 0 .. 31 */ - /******** Get Volume Name ***************/ - struct XDATA { - uint8 namelen; - uint8 name[16]; - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_volume_name((int)*(p+1), xdata->name); - if (result > -1) { - xdata->namelen = (uint8) result; - data_len = result+1; - } else completition = (uint8) -result; - } else if (*p == 0xa){ /* legt Verzeichnis an */ - /******** Create Dir *********************/ - int dir_handle = (int) *(p+1); #if 0 - int rightmask = (int) *(p+2); + case 0x18 : { /* restore directory handle */ + ????????? + } + break; #endif - int pathlen = (int) *(p+3); - uint8 *path = p+4; - int code = nw_mk_rd_dir(dir_handle, path, pathlen, 1); - if (code) completition = (uint8) -code; - } else if (*p == 0xb){ /* deletes dir */ - /******** Delete DIR *********************/ - int dir_handle = (int) *(p+1); + case 0x19 : { + /* Set Directory Information + * Modifies basic directory information as creation date and + * directory rights mask. DOS namespace. + */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; + uint8 creation_date[2]; + uint8 creation_time[2]; + uint8 owner_id[4]; + uint8 new_max_rights; + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_set_dir_info( + input->dir_handle, + input->path, input->pathlen, + GET_BE32(input->owner_id), + (int)input->new_max_rights, + input->creation_date, + input->creation_time); + if (result<0) completition = (uint8) -result; + /* No REPLY */ + } + break; + + case 0x1a : { /* Get Pathname of A Volume Dir Pair */ #if 0 - int reserved = (int) *(p+2); /* Res. by NOVELL */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 volume; + uint8 dir_entry[2]; + } *input = (struct INPUT *) (ncprequest); + struct XDATA { + uint8 pathlen; + uint8 pathname; + } *xdata = (struct XDATA*)responsedata; #endif - int pathlen = (int) *(p+3); - uint8 *path = p+4; - int code = nw_mk_rd_dir(dir_handle, path, pathlen, 0); - if (code) completition = (uint8) -code; - } else if (*p == 0xd){ /* Add Trustees to DIR */ - /******** AddTrustesstoDir ***************/ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* Verzeichnis Handle */ - uint8 trustee_id[4]; /* Trustee Object ID */ - uint8 trustee_right_mask; - uint8 pathlen; - uint8 path[2]; - } *input = (struct INPUT *) (ncprequest); - int result = nw_add_trustee( - input->dir_handle, - input->path, input->pathlen, - GET_BE32(input->trustee_id), - (int)input->trustee_right_mask, - 0); - if (result) completition = (uint8) -result; - } else if (*p == 0xf){ /* rename dir */ - /******** Rename DIR *********************/ - int dir_handle = (int) *(p+1); - int oldpathlen = (int) *(p+2); - uint8 *oldpath = p+3; - int newpathlen = (int) *(oldpath + oldpathlen); - uint8 *newpath = oldpath + oldpathlen + 1; - int code = mv_dir(dir_handle, - oldpath, oldpathlen, - newpath, newpathlen); - if (code) completition = (uint8) -code; - } else if (*p == 0x12 /* Allocate Permanent Dir Handle */ + completition = 0xfb; /* !!!!! TODO !!!! */ + } + break; + + case 0x1e : { /* SCAN a Directory, e.g. used by ndir.exe */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Verzeichnis Handle */ + uint8 attrib; /* Search Attrib z.B. 0x6 */ + uint8 searchsequence[4]; /* 32 bit */ + uint8 len; + uint8 data[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_scan_a_directory( + responsedata, + input->dir_handle, + input->data, + input->len, + input->attrib, + GET_BE32(input->searchsequence)); - /******** Allocate Permanent DIR Handle **/ - || *p == 0x13 /* Allocate Temp Dir Handle */ - /******** Allocate Temp DIR Handle **/ - || *p == 0x16) { /* Allocate Special Temp Dir Handle */ - /******** Allocate spez temp DIR Handle **/ - struct XDATA { - uint8 dirhandle; /* new Dir Handle */ - uint8 right_mask; /* 0xff effektive Right MAsk ? */ - } *xdata = (struct XDATA*) responsedata; - int dirhandle = nw_alloc_dir_handle( - (int) *(p+1), - p+4, - (int)*(p+3), - (int)*(p+2), - (*p==0x12) ? 0 - : ((*p==0x13) ? 1 : 2), - (int)(ncprequest->task)); - if (dirhandle > -1){ - xdata->dirhandle = (uint8) dirhandle; - xdata->right_mask = 0xff; - data_len = sizeof(struct XDATA); - } else completition = (uint8) -dirhandle; - - } else if (*p == 0x14){ /* deallocate Dir Handle */ - /******** Free DIR Handle ****************/ - int err_code = nw_free_dir_handle((int)*(p+1), - (int)(ncprequest->task)); - if (err_code) completition = (uint8) -err_code; - } else if (*p == 0x15){ /* liefert Volume Information */ - /******** Get Volume Info with Handle ****/ - struct XDATA { - uint8 sectors[2]; - uint8 total_blocks[2]; - uint8 avail_blocks[2]; - uint8 total_dirs[2]; /* anz dirs */ - uint8 avail_dirs[2]; /* free dirs */ - uint8 name[16]; /* SYS Name */ - uint8 removable[2]; - } *xdata = (struct XDATA*)responsedata; - int result = nw_get_vol_number((int)*(p+1)); - memset(xdata, 0, sizeof(struct XDATA)); - if (result > -1) { - int volume = result; - result = nw_get_volume_name(volume, xdata->name); - if (result > -1) { - struct fs_usage fsp; - if (!nw_get_fs_usage(xdata->name, &fsp, - entry8_flags&0x40 )) { - int sector_scale=1; - while (fsp.fsu_blocks/sector_scale > 0xffff) - sector_scale+=2; - U16_TO_BE16(sector_scale, xdata->sectors); - U16_TO_BE16(fsp.fsu_blocks/sector_scale, xdata->total_blocks); - U16_TO_BE16(fsp.fsu_bavail/sector_scale, xdata->avail_blocks); - U16_TO_BE16(fsp.fsu_files, xdata->total_dirs); - U16_TO_BE16(fsp.fsu_ffree, xdata->avail_dirs); - if (get_volume_options(volume) & VOL_OPTION_REMOUNT) { - U16_TO_BE16(1, xdata->removable); - } else { - U16_TO_BE16(0, xdata->removable); - } - } - data_len = sizeof(struct XDATA); - XDPRINTF((5,0,"GIVE VOLUME INFO from :%s:", xdata->name)); - result = 0; - } - } - completition = (uint8)-result; - } else if (*p == 0x19){ - /* Set Directory Information - * Modifies basic directory information as creation date and - * directory rights mask. DOS namespace. - */ -#if 0 - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; - uint8 creation_date[2]; - uint8 creation_time[2]; - uint8 owner_id[4]; - uint8 new_max_rights; - uint8 pathlen; - uint8 path; - } *input = (struct INPUT *) (ncprequest); -#endif - /* No REPLY */ - completition = 0xfb; /* !!!!! TODO !!!! */ - } else if (*p == 0x1a){ /* Get Pathname of A Volume Dir Pair */ -#if 0 - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 volume; - uint8 dir_entry[2]; - } *input = (struct INPUT *) (ncprequest); - struct XDATA { - uint8 pathlen; - uint8 pathname; - } *xdata = (struct XDATA*)responsedata; -#endif - completition = 0xfb; /* !!!!! TODO !!!! */ - } else if (*p == 0x1e){ - /* SCAN a Directory */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* Verzeichnis Handle */ - uint8 attrib; /* Search Attrib z.B. 0x6 */ - uint8 searchsequence[4]; /* 32 bit */ - uint8 len; - uint8 data[2]; - } *input = (struct INPUT *) (ncprequest); - int result = nw_scan_a_directory( - responsedata, - input->dir_handle, - input->data, - input->len, - input->attrib, - GET_BE32(input->searchsequence)); - - if (result > -1) data_len = result; - else completition = (uint8) (-result); - } else if (*p == 0x1f){ - /* SCAN a root dir ???? */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* Verzeichnis Handle */ - uint8 dont_know1; /* ???? 0xc0 */ - uint8 dont_know2; /* ???? 0xfa */ - } *input = (struct INPUT *) (ncprequest); - int result = nw_scan_a_root_dir( - responsedata, - input->dir_handle); - if (result > -1) data_len = result; - else completition = (uint8) (-result); - } else if (*p == 0x20){ - /* scan volume user disk restrictions */ - uint8 volnr = *(p+1); - /* uint32 sequenz = GET_BE32(p+2); */ - struct XDATA { - uint8 entries; /* 0x0 */ - /*--- per entry (max.entries = 12) ----*/ - uint8 id[4]; - uint8 restriction[4]; - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_volume_name(volnr, NULL); - if (result > -1) { - xdata->entries = 0x0; - data_len = (8 * xdata->entries) + 1; - } else completition = (uint8) (-result); - } else if (*p == 0x21) { - /* change Vol restrictions for Obj */ - XDPRINTF((5, 0, "Change vol restrictions")); - return(-2); /* nwbind must do prehandling */ - } else if (*p == 0x22) { - /* remove Vol restrictions for Obj */ - XDPRINTF((5, 0, "Remove vol restrictions")); - return(-2); /* nwbind must do prehandling */ - } else if (*p == 0x25){ - /* Set Entry, Set Directory File Information - * sets or changes the file or directory information to the - * values entered in 'Change Bits'. - */ - /* NO REPLY */ - /* ncopy use this call */ - /* TODO !!!!!!!!!!!!!!!!!!!! */ - - do_druck++; - - } else if (*p == 0x26) { /* Scan file or Dir for ext trustees */ - int sequenz = (int)*(p+2); /* trustee sequenz */ - struct XDATA { - uint8 entries; - uint8 ids[80]; /* 20 id's */ - uint8 trustees[40]; /* 20 trustees's */ - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_eff_dir_rights( - (int)*(p+1), - p+4, - (int)*(p+3), 1); - if (result > -1){ - if (!sequenz) { - memset(xdata, 0, sizeof(struct XDATA)); - xdata->entries=1; -#if 0 - U32_TO_BE32(1, xdata->ids); /* SUPERVISOR */ -#else - U32_TO_BE32(act_obj_id, xdata->ids); /* actual LOGIN User */ - /* NOTE: this should be made better */ -#endif - xdata->trustees[1] = 0x1; /* Supervisory */ - xdata->trustees[0] = 0xff; /* all low */ - data_len = sizeof(struct XDATA); - } else completition = 0x9c; /* no more trustees */ - } else completition = (uint8) (-result); - } else if (*p == 0x27) { /* Add Ext Trustees to DIR or File */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* Handle */ - uint8 trustee_id[4]; /* Trustee Object ID */ - uint8 trustee_rights[2]; /* low - high */ - uint8 pathlen; - uint8 path[2]; - } *input = (struct INPUT *) (ncprequest); - int result = nw_add_trustee( - input->dir_handle, - input->path, input->pathlen, - GET_BE32(input->trustee_id), - GET_16(input->trustee_rights), - 1); /* extended */ - if (result) completition = (uint8) -result; - } else if (*p == 0x28){ - /* Scan File Physical ??? */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0x0, dlen, ufunc */ - uint8 dir_handle; /* directory handle */ - uint8 attrib; /* Search Attrib ?? 0x2f */ - uint8 searchsequence[4]; /* 32 bit */ - uint8 len; - uint8 data[2]; - } *input = (struct INPUT *) (ncprequest); - /* we try, whether this is ok ????? */ - int result = nw_scan_a_directory( - responsedata, - input->dir_handle, - input->data, - input->len, - input->attrib, - GET_BE32(input->searchsequence)); - if (result > -1) data_len = result; - else completition = (uint8) (-result); - } else if (*p == 0x29){ - /* read volume restrictions for an object */ + if (result > -1) data_len = result; + else completition = (uint8) (-result); + } + break; + + case 0x1f : { /* SCAN a root dir ???? */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Verzeichnis Handle */ + uint8 dont_know1; /* ???? 0xc0 */ + uint8 dont_know2; /* ???? 0xfa */ + } *input = (struct INPUT *) (ncprequest); + int result = nw_scan_a_root_dir( + responsedata, + input->dir_handle); + if (result > -1) data_len = result; + else completition = (uint8) (-result); + } + break; + + case 0x20 : { /* scan volume user disk restrictions */ + uint8 volnr = *(p+1); + /* uint32 sequence = GET_BE32(p+2); */ + struct XDATA { + uint8 entries; /* 0x0 */ + /*--- per entry (max.entries = 12) ----*/ + uint8 id[4]; + uint8 restriction[4]; + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_volume_name(volnr, NULL, 0); + if (result > -1) { + xdata->entries = 0x0; + data_len = (8 * xdata->entries) + 1; + } else completition = (uint8) (-result); + } + break; + + case 0x21 : { /* change Vol restrictions for Obj */ + XDPRINTF((5, 0, "Change vol restrictions")); + } + return(-2); /* nwbind must do prehandling */ + + case 0x22 : { /* remove Vol restrictions for Obj */ + XDPRINTF((5, 0, "Remove vol restrictions")); + } + return(-2); /* nwbind must do prehandling */ + + case 0x25 : { /* Set Entry, Set Directory File Information + * sets or changes the file or directory information to the + * values entered in 'Change Bits'. + * NO REPLY + * used by ncopy.exe, flag.exe + */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; + uint8 attrib; + NW_SET_DIR_INFO f; + } *input = (struct INPUT *) (ncprequest); + int result = nw_set_a_directory_entry( + input->dir_handle, + input->f.u.f.name, + input->f.u.f.namlen, + input->attrib, + GET_BE32(input->f.searchsequence), + &(input->f)); + if (result<0) + do_druck++; + /* TODO !!!!!!! */ + } + break; + + case 0x26 : { /* Scan file or Dir for ext trustees */ + int sequence = (int)*(p+2); /* trustee sequence */ + struct XDATA { + uint8 entries; + uint8 ids[80]; /* 20 id's */ + uint8 trustees[40]; /* 20 trustees's */ + } *xdata = (struct XDATA*) responsedata; + uint32 ids[20]; + int trustees[20]; + int result = nw_scan_for_trustee( + (int)*(p+1), /* dir handle */ + sequence, + p+4, /* path */ + (int)*(p+3), /* pathlen */ + 20, /* max entries */ + ids, + trustees, + 1); /* extended */ + if (result > -1) { + int i = -1; + uint8 *idsp = xdata->ids; + uint8 *trp = xdata->trustees; + memset(xdata, 0, sizeof(*xdata)); + xdata->entries = result; + while(++i < result) { + U32_TO_BE32(ids[i], idsp); + idsp+=4; + U16_TO_16(trustees[i], trp); /* LO - HI */ + trp+=2; + } + data_len = sizeof(struct XDATA); + } else completition = (uint8) (-result); + } + break; + + case 0x27 : { /* Add Ext Trustees to DIR or File */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Handle */ + uint8 trustee_id[4]; /* Trustee Object ID */ + uint8 trustee_rights[2]; /* lo - hi */ + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_add_trustee( + input->dir_handle, + input->path, input->pathlen, + GET_BE32(input->trustee_id), + GET_16(input->trustee_rights), + 1); /* extended */ + if (result) completition = (uint8) -result; + } + break; + + case 0x28 : { /* Scan File Physical ??? */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* directory handle */ + uint8 attrib; /* Search Attrib ?? 0x2f */ + uint8 searchsequence[4]; /* 32 bit */ + uint8 len; + uint8 data[2]; + } *input = (struct INPUT *) (ncprequest); + /* we try, whether this is ok ????? */ + int result = nw_scan_a_directory( + responsedata, + input->dir_handle, + input->data, + input->len, + input->attrib, + GET_BE32(input->searchsequence)); + if (result > -1) data_len = result; + else completition = (uint8) (-result); + } + break; + + case 0x29 : { /* read volume restrictions for an object */ #if QUOTA_SUPPORT - XDPRINTF((5, 0, "Read vol restrictions")); - return(-2); /* nwbind must do prehandling */ + XDPRINTF((5, 0, "Read vol restrictions")); + return(-2); /* nwbind must do prehandling */ #else #if DO_DEBUG - uint8 volnr = *(p+1); - uint32 id = GET_BE32(p+2); + uint8 volnr = *(p+1); + uint32 id = GET_BE32(p+2); #endif - struct XDATA { - uint8 restriction[4]; - uint8 inuse[4]; - } *xdata = (struct XDATA*) responsedata; - XDPRINTF((5,0, "Get vol restriction (DUMMY) vol=%d, id=0x%lx", - (int)volnr, id)); - U32_TO_32(0x40000000, xdata->restriction); - U32_TO_32(0x0, xdata->inuse); - data_len=sizeof(struct XDATA); + struct XDATA { + uint8 restriction[4]; + uint8 inuse[4]; + } *xdata = (struct XDATA*) responsedata; + XDPRINTF((5,0, "Get vol restriction (DUMMY) vol=%d, id=0x%lx", + (int)volnr, id)); + U32_TO_32(0x40000000, xdata->restriction); + U32_TO_32(0x0, xdata->inuse); + data_len=sizeof(struct XDATA); #endif - } else if (*p == 0x2a){ - /* Get Eff. Rights of DIR's and Files ??*/ - struct XDATA { - uint8 eff_rights; /* Effektive Right to Dir */ - uint8 unkwown_data; /* 0x1 */ - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_eff_dir_rights( - (int)*(p+1), - p+3, - (int)*(p+2), 1); - if (result > -1){ - xdata->eff_rights = (uint8)result; - xdata->unkwown_data = 0x1; - data_len = sizeof(struct XDATA); - } else completition = (uint8) (-result); - } else if (*p == 0x2c){ - /* Get Volume and Purge Information */ - /* new Call since V3.11 */ - /* ncpfs need this call */ - int volume = (int) *(p+1); - struct XDATA { - uint8 total_blocks[4]; /* LOW-HI !! */ - uint8 avail_blocks[4]; - uint8 purgeable_blocks[4]; - uint8 not_purgeable_blocks[4]; - uint8 total_dirs[4]; - uint8 avail_dirs[4]; - uint8 reserved_by_novell[4]; - uint8 sec_per_block; - uint8 namlen; - uint8 name[1]; - } *xdata = (struct XDATA*) responsedata; - uint8 name[100]; - int result = nw_get_volume_name(volume, name); - if (result > -1){ - struct fs_usage fsp; - memset(xdata, 0, sizeof(struct XDATA)); - if (!nw_get_fs_usage(name, &fsp, 0)) { - xdata->sec_per_block = 8; /* hard coded */ - U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks); - U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks); - U32_TO_32(fsp.fsu_files, xdata->total_dirs); - U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs); - } - xdata->namlen = strlen((char*)name); - strmaxcpy(xdata->name, name, xdata->namlen); - data_len = xdata->namlen + 30; - } else completition = (uint8) -result; - } else if (*p == 0x2d){ - /* Get Direktory Information */ - int dir_handle = (int) *(p+1); - struct XDATA { - uint8 total_blocks[4]; - uint8 avail_blocks[4]; - uint8 total_dirs[4]; - uint8 avail_dirs[4]; - uint8 reserved_by_novell[4]; - uint8 sec_per_block; - uint8 namlen; - uint8 name[1]; /* Volume Name */ - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_vol_number(dir_handle); - uint8 name[100]; - if (result > -1) - result = nw_get_volume_name(result, name); - if (result > -1) { - struct fs_usage fsp; - memset(xdata, 0, sizeof(struct XDATA)); - if (!nw_get_fs_usage(name, &fsp, 0)) { - xdata->sec_per_block = 8; /* hard coded */ - U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks); - U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks); - U32_TO_32(fsp.fsu_files, xdata->total_dirs); - U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs); - } - xdata->namlen = strlen((char*)name); - strmaxcpy(xdata->name, name, xdata->namlen); - data_len = xdata->namlen + 22; - } else completition = (uint8) -result; - } else if (*p == 0x2e){ /* RENAME DATEI */ - completition = 0xfb; /* TODO: !!! */ + } + break; + + case 0x2a : { /* Get Eff. Rights of DIR's and Files */ + struct XDATA { + uint8 eff_rights[2]; /* LO-HI */ + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_eff_dir_rights( + (int)*(p+1), + p+3, + (int)*(p+2), 1); + if (result > -1){ + U16_TO_16(result, xdata->eff_rights); + data_len = sizeof(struct XDATA); + } else completition = (uint8) (-result); + } + break; + + case 0x2b : { /* remove ext trustees */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 dir_handle; /* Handle */ + uint8 trustee_id[4]; /* Trustee Object ID */ + uint8 reserved; + uint8 pathlen; + uint8 path[2]; + } *input = (struct INPUT *) (ncprequest); + int result = nw_del_trustee( + input->dir_handle, + input->path, input->pathlen, + GET_BE32(input->trustee_id), + 1); /* extended */ + if (result) completition = (uint8) -result; + } + break; + + case 0x2c : { /* Get Volume and Purge Information */ + /* new Call since V3.11 */ + /* ncpfs need this call */ + int volume = (int) *(p+1); + struct XDATA { + uint8 total_blocks[4]; /* LOW-HI !! */ + uint8 avail_blocks[4]; + uint8 purgeable_blocks[4]; + uint8 not_purgeable_blocks[4]; + uint8 total_dirs[4]; + uint8 avail_dirs[4]; + uint8 reserved_by_novell[4]; + uint8 sec_per_block; + uint8 namlen; + uint8 name[1]; + } *xdata = (struct XDATA*) responsedata; + uint8 name[100]; + int result = nw_get_volume_name(volume, name, sizeof(name)); + if (result > -1){ + struct fs_usage fsp; + memset(xdata, 0, sizeof(struct XDATA)); + if (!nw_get_fs_usage(name, &fsp, 0)) { + xdata->sec_per_block = 8; /* hard coded */ + U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks); + U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks); + U32_TO_32(fsp.fsu_files, xdata->total_dirs); + U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs); + } + xdata->namlen = strlen((char*)name); + strmaxcpy(xdata->name, name, xdata->namlen); + data_len = xdata->namlen + 30; + } else completition = (uint8) -result; + } + break; + + case 0x2d : { /* Get Direktory Information */ + int dir_handle = (int) *(p+1); + struct XDATA { + uint8 total_blocks[4]; + uint8 avail_blocks[4]; + uint8 total_dirs[4]; + uint8 avail_dirs[4]; + uint8 reserved_by_novell[4]; + uint8 sec_per_block; + uint8 namlen; + uint8 name[1]; /* Volume Name */ + } *xdata = (struct XDATA*) responsedata; + int result = nw_get_vol_number(dir_handle); + uint8 name[100]; + if (result > -1) + result = nw_get_volume_name(result, name, sizeof(name)); + if (result > -1) { + struct fs_usage fsp; + memset(xdata, 0, sizeof(struct XDATA)); + if (!nw_get_fs_usage(name, &fsp, 0)) { + xdata->sec_per_block = 8; /* hard coded */ + U32_TO_32(fsp.fsu_blocks/8, xdata->total_blocks); + U32_TO_32(fsp.fsu_bavail/8, xdata->avail_blocks); + U32_TO_32(fsp.fsu_files, xdata->total_dirs); + U32_TO_32(fsp.fsu_ffree, xdata->avail_dirs); + } + xdata->namlen = strlen((char*)name); + strmaxcpy(xdata->name, name, xdata->namlen); + data_len = xdata->namlen + 22; + } else completition = (uint8) -result; + } + break; + + case 0x2e : { /* rename file */ + completition = 0xfb; /* TODO: !!! */ + } + break; #if WITH_NAME_SPACE_CALLS - } else if (*p == 0x2f){ - /* Fill namespace buffer */ - /* ncopy use this call */ - int volume = (int) *(p+1); - /* (p+2) == 0xe4 or 0xe2 sometimes ???? */ - int result=fill_namespace_buffer( - volume, responsedata); - if (result > -1) { - data_len = result; - } else completition = (uint8) -result; - } else if (*p == 0x30){ - /* Get Name Space Directory Entry */ - int volume = (int) *(p+1); - uint32 basehandle = GET_32(p+2); - int namespace = (int) *(p+6); - int result=get_namespace_dir_entry( - volume, basehandle, namespace, - responsedata); - if (result > -1) { - data_len = result; - } else completition = (uint8) -result; + + case 0x2f : { /* Fill namespace buffer */ + /* ncopy use this call */ + int volume = (int) *(p+1); + /* (p+2) == 0xe4 or 0xe2 sometimes ???? */ + int result=fill_namespace_buffer( + volume, responsedata); + if (result > -1) { + data_len = result; + } else completition = (uint8) -result; + } + break; + + case 0x30 : { /* Get Name Space Directory Entry */ + int volume = (int) *(p+1); + uint32 basehandle = GET_32(p+2); + int namespace = (int) *(p+6); + int result=get_namespace_dir_entry( + volume, basehandle, namespace, + responsedata); + if (result > -1) { + data_len = result; + } else completition = (uint8) -result; + } + break; #endif - } else completition = 0xfb; /* unkwown request */ - } - break; - case 0x17 : { /* FILE SERVER ENVIRONMENT */ - /* uint8 len = *(requestdata+1); */ - uint8 ufunc = *(requestdata+2); - uint8 *rdata = requestdata+3; + case 0x33 : { /* Get Extended Volume Information */ +#if 0 + int volume = (int) *(p+1); + /* next 3 byte are low bytes of volume */ +#endif + completition = 0xfb; /* not known yet */ + } + break; - switch (ufunc) { + + default: + completition = 0xfb; /* unkwown request */ + break; + } /* switch *p */ + } + break; + + + case 0x17 : { /* FILE SERVER ENVIRONMENT */ + /* uint8 len = *(requestdata+1); */ + uint8 ufunc = *(requestdata+2); + uint8 *rdata = requestdata+3; + + switch (ufunc) { #if FUNC_17_02_IS_DEBUG - case 0x02 : { - /* I hope this call isn't used */ - /* now missused as a debug switch :) */ - struct XDATA { - uint8 nw_debug; /* old level */ - } *xdata = (struct XDATA*) responsedata; - if (*rdata == NWCONN) { - xdata->nw_debug = (uint8)org_nw_debug; - nw_debug = org_nw_debug = (int) *(rdata+1); - data_len = 1; - } else return(-1); - } - break; + case 0x02 : { + /* I hope this call isn't used */ + /* now missused as a debug switch :) */ + struct XDATA { + uint8 nw_debug; /* old level */ + } *xdata = (struct XDATA*) responsedata; + if (*rdata == NWCONN) { + xdata->nw_debug = (uint8)org_nw_debug; + nw_debug = org_nw_debug = (int) *(rdata+1); + data_len = 1; + } else return(-1); + } + break; #endif - case 0x14: /* Login Objekt, unencrypted passwords */ - case 0x18: /* crypt_keyed LOGIN */ - return(-2); /* nwbind must do prehandling */ + case 0x14: /* Login Objekt, unencrypted passwords */ + case 0x18: /* crypt_keyed LOGIN */ + return(-2); /* nwbind must do prehandling */ - case 0x0f: { /* Scan File Information */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0, len + ufunc */ - uint8 sequence[2]; /* z.B. 0xff, 0xff */ - uint8 dir_handle; - uint8 search_attrib; /* 0: NONE */ - /* 02: HIDDEN */ - /* 04: SYSTEM */ - /* 06: BOTH */ - /* 0x10: DIR */ - uint8 len; - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; + case 0x0f: { /* Scan File Information */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0, len + ufunc */ + uint8 sequence[2]; /* z.B. 0xff, 0xff */ + uint8 dir_handle; + uint8 search_attrib; /* 0: NONE */ + /* 02: HIDDEN */ + /* 04: SYSTEM */ + /* 06: BOTH */ + /* 0x10: DIR */ + uint8 len; + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 sequence[2]; /* next sequence */ - /* NW_FILE_INFO f; */ - uint8 f[sizeof(NW_FILE_INFO)]; - uint8 owner_id[4]; - uint8 archive_date[2]; - uint8 archive_time[2]; - uint8 reserved[56]; - } *xdata = (struct XDATA*)responsedata; - int len = input->len; - int searchsequence; - NW_FILE_INFO f; - uint32 owner; + struct XDATA { + uint8 sequence[2]; /* next sequence */ + /* NW_FILE_INFO f; */ + uint8 f[sizeof(NW_FILE_INFO)]; + uint8 owner_id[4]; + uint8 archive_date[2]; + uint8 archive_time[2]; + uint8 reserved[56]; + } *xdata = (struct XDATA*)responsedata; + int len = input->len; + int searchsequence; + NW_FILE_INFO f; + uint32 owner; - memset(xdata, 0, sizeof(struct XDATA)); - searchsequence = nw_search( (uint8*) &f, - &owner, - (int)input->dir_handle, - (int) GET_BE16(input->sequence), - (int) input->search_attrib, - input->data, len); - if (searchsequence > -1) { - memcpy(xdata->f, &f, sizeof(NW_FILE_INFO)); - U16_TO_BE16((uint16) searchsequence, xdata->sequence); - U32_TO_BE32(owner, xdata->owner_id); - data_len = sizeof(struct XDATA); - } else completition = (uint8) (- searchsequence); - } - break; + memset(xdata, 0, sizeof(struct XDATA)); + searchsequence = nw_search( (uint8*) &f, + &owner, + (int)input->dir_handle, + (int) GET_BE16(input->sequence), + (int) input->search_attrib & ~0x10, + /* this routine is only for scanning files ^^^^^^ */ + input->data, len); + if (searchsequence > -1) { + memcpy(xdata->f, &f, sizeof(NW_FILE_INFO)); + U16_TO_BE16((uint16) searchsequence, xdata->sequence); + U32_TO_BE32(owner, xdata->owner_id); + data_len = sizeof(struct XDATA); + } else completition = (uint8) (- searchsequence); + } + break; - case 0x10: { /* Set File Information */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 div[3]; /* 0, len + ufunc */ - uint8 f[sizeof(NW_FILE_INFO) - 14]; /* no name */ - uint8 owner_id[4]; - uint8 archive_date[2]; - uint8 archive_time[2]; - uint8 reserved[56]; - uint8 dir_handle; - uint8 search_attrib; /* 0: NONE */ - /* 02: HIDDEN */ - /* 04: SYSTEM */ - /* 06: BOTH */ - /* 0x10: DIR */ - uint8 len; - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - NW_FILE_INFO f; - int result; - memcpy(((uint8*)&f)+14, input->f, sizeof(NW_FILE_INFO)-14); - result = nw_set_file_information((int)input->dir_handle, - input->data, - (int)input->len, - (int)input->search_attrib, &f); - /* no reply packet */ - if (result <0) completition = (uint8)-result; - } - break; + case 0x10: { /* Set File Information */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0, len + ufunc */ + uint8 f[sizeof(NW_FILE_INFO) - 14]; /* no name */ + uint8 owner_id[4]; + uint8 archive_date[2]; + uint8 archive_time[2]; + uint8 reserved[56]; + uint8 dir_handle; + uint8 search_attrib; /* 0: NONE */ + /* 02: HIDDEN */ + /* 04: SYSTEM */ + /* 06: BOTH */ + /* 0x10: DIR */ + uint8 len; + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + NW_FILE_INFO f; + int result; + memcpy(((uint8*)&f)+14, input->f, sizeof(NW_FILE_INFO)-14); + result = nw_set_file_information((int)input->dir_handle, + input->data, + (int)input->len, + (int)input->search_attrib, &f); + /* no reply packet */ + if (result <0) completition = (uint8)-result; + } + break; - case 0x64: { /* create queue */ + case 0x47 : { /* SCAN BINDERY OBJECT TRUSTEE PATH */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 div[3]; /* 0x0, dlen, ufunc */ + uint8 volume; + uint8 sequence[2]; /* trustee searchsequence */ + uint8 id[4]; /* Trustee Object ID */ + } *input = (struct INPUT *) (ncprequest); + struct XDATA { + uint8 nextsequence[2]; + uint8 id[4]; + uint8 access_mask; + uint8 pathlen; + uint8 path[1]; + } *xdata = (struct XDATA*) responsedata; + int sequence=GET_BE16(input->sequence); + int access_mask=0; + uint32 id=GET_BE32(input->id); + int result=nw_scan_user_trustee( + input->volume, &sequence, id, &access_mask, xdata->path); + if (result > 0) { + U16_TO_BE16(sequence, xdata->nextsequence); + memcpy(xdata->id, input->id, 4); + xdata->access_mask=(uint8)access_mask; + xdata->pathlen=result; + data_len = 8+result; + } else if (!result) { + memset(xdata, 0, 8); + data_len = 8; + } else + completition = (uint8)(-result); + } + break; + + case 0x64: { /* create queue */ #if 0 - int q_typ = GET_BE16(rdata); + int q_typ = GET_BE16(rdata); #endif - int q_name_len = *(rdata+2); + int q_name_len = *(rdata+2); #if 0 - uint8 *q_name = rdata+3; + uint8 *q_name = rdata+3; #endif - uint8 *dirhandle = rdata+3+q_name_len; - int pathlen = *(rdata+3+q_name_len+1); - uint8 *path = rdata+3+q_name_len+2; - uint8 new_path[257]; - int result = conn_get_full_path(*dirhandle, - path, pathlen, new_path); - if (result > -1) { - int diffsize = result - pathlen; - *dirhandle = 0; - memcpy(path, new_path, result); - if (diffsize) - requestlen+=diffsize; /* !!!!!! */ - return(-1); /* nwbind must do the rest */ - } else - completition = (uint8)(-result); - } - break; + uint8 *dirhandle = rdata+3+q_name_len; + int pathlen = *(rdata+3+q_name_len+1); + uint8 *path = rdata+3+q_name_len+2; + uint8 new_path[257]; + int result = conn_get_full_path(*dirhandle, + path, pathlen, new_path, + sizeof(new_path)); + if (result > -1) { + int diffsize = result - pathlen; + *dirhandle = 0; + memcpy(path, new_path, result); + if (diffsize) + requestlen+=diffsize; /* !!!!!! */ + return(-1); /* nwbind must do the rest */ + } else + completition = (uint8)(-result); + } + break; - case 0x68: /* create queue job and file old */ - case 0x79: /* create queue job and file */ - return(-2); /* nwbind must do prehandling */ + case 0x68: /* create queue job and file old */ + case 0x79: /* create queue job and file */ + return(-2); /* nwbind must do prehandling */ + 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); + uint32 fhandle = get_queue_job_fhandle(q_id, job_id); + U32_TO_BE32(fhandle, rdata+8); + requestlen+=6; /* !!!!!! */ + } + return(-1); /* nwbind must do the rest */ - case 0x6C: { /* Get Queue Job Entry old */ - uint32 q_id = GET_BE32(rdata); - int job_id = GET_BE16(rdata+4); - uint32 fhandle = get_queue_job_fhandle(q_id, job_id); - U32_TO_BE32(fhandle, rdata+8); - requestlen+=6; /* !!!!!! */ - } - return(-1); /* nwbind must do the rest */ + case 0x69: /* close file and start queue old ?? */ + case 0x7f: { /* close file and start queue */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 packetlen[2]; /* lo - hi */ + uint8 func; /* 0x7f or 0x69 */ + uint8 queue_id[4]; /* Queue ID */ + uint8 job_id[4]; /* result from creat queue */ + /* if 0x69 then only first 2 byte ! */ + } *input = (struct INPUT *) (ncprequest); + uint32 q_id = GET_BE32(input->queue_id); + int job_id = (ufunc==0x69) ? GET_BE16(input->job_id) + : GET_BE16(input->job_id); + int result = close_queue_job(q_id, job_id); + if (result < 0) { + completition = (uint8)-result; + } else { + return(-2); /* nwbind must do next */ + } + } + break; - case 0x69: /* close file and start queue old ?? */ - case 0x7f: { /* close file and start queue */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 packetlen[2]; /* low high */ - uint8 func; /* 0x7f or 0x69 */ - uint8 queue_id[4]; /* Queue ID */ - uint8 job_id[4]; /* result from creat queue */ - /* if 0x69 then only first 2 byte ! */ - } *input = (struct INPUT *) (ncprequest); - uint32 q_id = GET_BE32(input->queue_id); - int job_id = (ufunc==0x69) ? GET_BE16(input->job_id) - : GET_BE16(input->job_id); - int result = close_queue_job(q_id, job_id); - if (result < 0) { - completition = (uint8)-result; - } else { - return(-2); /* nwbind must do next */ - } - } - break; + case 0x71 : /* service queue job (old) */ + case 0x7c : /* service queue job */ + return(-2); /* nwbind must do prehandling */ - case 0x71 : /* service queue job (old) */ - case 0x7c : /* service queue job */ - return(-2); /* nwbind must do prehandling */ + case 0x72 : /* finish queue job (old) */ + case 0x73 : /* abort queue job (old) */ + case 0x83 : /* finish queue job */ + case 0x84 : { /* abort queue job */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 packetlen[2]; /* low high */ + uint8 func; /* 0x7f or 0x69 */ + uint8 queue_id[4]; /* Queue ID */ + uint8 job_id[4]; /* result from creat queue */ + /* if 0x69 then only first 2 byte ! */ + } *input = (struct INPUT *) (ncprequest); + uint32 q_id = GET_BE32(input->queue_id); + int job_id = GET_BE16(input->job_id); + int result = finish_abort_queue_job(q_id, job_id); + if (result <0) + completition=(uint8) -result; + else + return(-1); /* nwbind must do the rest */ + } + break; - case 0x72 : /* finish queue job (old) */ - case 0x73 : /* abort queue job (old) */ - case 0x83 : /* finish queue job */ - case 0x84 : { /* abort queue job */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 packetlen[2]; /* low high */ - uint8 func; /* 0x7f or 0x69 */ - uint8 queue_id[4]; /* Queue ID */ - uint8 job_id[4]; /* result from creat queue */ - /* if 0x69 then only first 2 byte ! */ - } *input = (struct INPUT *) (ncprequest); - uint32 q_id = GET_BE32(input->queue_id); - int job_id = GET_BE16(input->job_id); - int result = finish_abort_queue_job(q_id, job_id); - if (result <0) - completition=(uint8) -result; - else - return(-1); /* nwbind must do the rest */ - } - break; + case 0xf3: { /* Map Direktory Number TO PATH */ + XDPRINTF((2,0, "TODO: Map Directory Number TO PATH")); + completition = 0xff; + } + break; - case 0xf3: { /* Map Direktory Number TO PATH */ - XDPRINTF((2,0, "TODO: Map Directory Number TO PATH")); - completition = 0xff; - } - break; + case 0xf4: { /* Map PATH TO Dir Entry */ + XDPRINTF((2,0, "TODO: Map PATH TO Dir Entry")); + completition = 0xff; + } + break; - case 0xf4: { /* Map PATH TO Dir Entry */ - XDPRINTF((2,0, "TODO: Map PATH TO Dir Entry")); - completition = 0xff; - } - break; + default : return(-1); + break; + } /* switch (ufunc) */ + } /* case 0x17 */ + break; - default : return(-1); - break; - } /* switch (ufunc) */ - } /* case 0x17 */ - break; + case 0x18 : /* End of Job */ + if (!(entry8_flags&0x200)) /* pcz: 14-Apr-00 */ + free_connection_task_jobs(ncprequest->task); + nw_free_handles(ncprequest->task); + return(-1); /* nwbind must do a little rest */ + break; - case 0x18 : /* End of Job */ - nw_free_handles(ncprequest->task); - break; + case 0x19 : /* logout, some of this call is handled in ncpserv. */ + free_queue_jobs(); + nw_free_handles(-1); + set_nw_user(-1, -1, + 0, + 0, NULL, + -1, NULL, + 0, NULL); + return(-1); /* nwbind must do a little rest */ + break; - case 0x19 : /* logout, some of this call is handled in ncpserv. */ - free_queue_jobs(); - nw_free_handles(-1); - set_nw_user(-1, -1, - 0, NULL, - -1, NULL); - return(-1); /* nwbind must do a little rest */ - break; + case 0x1a : /* Log Physical Record */ + case 0x1e : /* Clear Physical Record */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 lock_flag; /* 0=log, 1=excl */ + /* 3=shared */ + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* Filehandle */ + uint8 offset[4]; + uint8 size[4]; + uint8 timeout[2]; + } *input = (struct INPUT *)ncprequest; + int fhandle = GET_32 (input->fhandle); + uint32 offset= GET_BE32(input->offset); + uint32 size = GET_BE32(input->size); + if (function == 0x1a) /* lockfile */ + completition = (uint8)(-nw_log_physical_record( + fhandle, + offset, + size, + (int)input->lock_flag)); + else + completition = (uint8)(-nw_log_physical_record( + fhandle, + offset, + size, + -2 /* unlock + unlog */ + )); + } + break; - case 0x20 : /* Semaphore */ - return(-1); /* handled by nwbind */ + case 0x1f : /* Clear Physical Record Set, DUMMY */ + XDPRINTF((1,0,"Clear Physical Record Set called, still DUMMY")); + break; - case 0x1a : /* lock file */ - case 0x1e : /* unlock file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 reserve; /* 0x1, lock-flag ? */ - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* Filehandle */ - uint8 offset[4]; - uint8 size[4]; - uint8 unknown[2]; /* lock timeout ??? */ - } *input = (struct INPUT *)ncprequest; - int fhandle = GET_32 (input->fhandle); - uint32 offset= GET_BE32(input->offset); - uint32 size = GET_BE32(input->size); - completition = (uint8)(-nw_lock_file(fhandle, - offset, size, - (int)(function == 0x1a))); - } - break; + case 0x20 : /* Semaphore */ + return(-1); /* handled by nwbind */ + + case 0x21 : { /* Negotiate Buffer Size, Packetsize */ + uint8 *getsize=responsedata; + int buffer_size = (int) (GET_BE16((uint8*)requestdata)); + /* Der Novell-Client der PAM's Net/E-Ethernetkarte + für Atari ST/TT meldet ein Packetsize von 0 wenn + nwserv NACH dem Novell Client NET_S1.PRG + gestartet wird. Da 0 in jedem Falle ein unsinniger + Wert ist, wird rw_buffer_size nicht verwendet. + Hayo Schmidt <100305.1424@compuserve.com>, 7-Dec-97 + */ + if (buffer_size >= 512) { + rw_buffer_size = min(LOC_RW_BUFFERSIZE, buffer_size); + XDPRINTF((3,0, "Negotiate Buffer size = 0x%04x,(%d)", + (int) rw_buffer_size, (int) rw_buffer_size)); + } else { + XDPRINTF((1,0, "Invalid Packetsize = %d, " + "Negotiate Buffer Size is set to %d", + buffer_size, rw_buffer_size)); + } + U16_TO_BE16(rw_buffer_size, getsize); + data_len = 2; + } + break; - case 0x21 : { /* Negotiate Buffer Size, Packetsize */ - uint8 *getsize=responsedata; - int buffer_size = (int) (GET_BE16((uint8*)requestdata)); - /* Der Novell-Client der PAM's Net/E-Ethernetkarte - für Atari ST/TT meldet ein Packetsize von 0 wenn - nwserv NACH dem Novell Client NET_S1.PRG - gestartet wird. Da 0 in jedem Falle ein unsinniger - Wert ist, wird rw_buffer_size nicht verwendet. - Hayo Schmidt <100305.1424@compuserve.com>, 7-Dec-97 - */ - if (buffer_size >= 512) { - rw_buffer_size = min(LOC_RW_BUFFERSIZE, buffer_size); - XDPRINTF((2,0, "Negotiate Buffer size = 0x%04x,(%d)", - (int) rw_buffer_size, (int) rw_buffer_size)); - } else { - XDPRINTF((1,0, "Invalid Packetsize = %d, " - "Negotiate Buffer Size is set to %d", - buffer_size, rw_buffer_size)); - } - U16_TO_BE16(rw_buffer_size, getsize); - data_len = 2; - } - break; + case 0x22 : { /* div TTS Calls */ + int ufunc = (int) *requestdata; + if (!ufunc) completition=0; /* TTS not availible */ + else completition=0xfb; /* request not known */ + } break; - case 0x22 : { /* div TTS Calls */ - int ufunc = (int) *requestdata; - if (!ufunc) completition=0; /* TTS not availible */ - else completition=0xfb; /* request not known */ - } break; - - case 0x23 : { /* div AFP Calls */ + case 0x23 : { /* div AFP Calls */ #if 0 - int ufunc = (int) *requestdata; + int ufunc = (int) *requestdata; #endif - completition=0xbf; /* we say invalid namespace here */ - } break; + completition=0xbf; /* we say invalid namespace here */ + } break; - case 0x3b : /* commit file to disk */ - case 0x3d : /* commit file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 reserve; - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* filehandle */ - } *input = (struct INPUT *)ncprequest; - uint32 fhandle = GET_32(input->fhandle); - int result=nw_commit_file(fhandle); - if (result<0) - completition=(uint8)-result; - } - break; + case 0x3b : /* commit file to disk */ + case 0x3d : /* commit file */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 reserve; + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* filehandle */ + } *input = (struct INPUT *)ncprequest; + uint32 fhandle = GET_32(input->fhandle); + int result=nw_commit_file(fhandle); + if (result<0) + completition=(uint8)-result; + } + break; - case 0x3e : { /* FILE SEARCH INIT */ - /* returns dhandle for searchings */ - int dir_handle = (int)*requestdata; - int len = (int)*(requestdata+1); /* pathlen */ - uint8 *p = requestdata+2; /* path */ - struct XDATA { - uint8 volume; /* Volume */ - uint8 dir_id[2]; /* Direktory ID */ - uint8 searchsequenz[2]; - uint8 dir_rights; /* Rights */ - } *xdata= (struct XDATA*) responsedata; - int volume; - int searchsequenz; - int dir_id; - int rights = nw_open_dir_handle(dir_handle, p, len, - &volume, &dir_id, &searchsequenz); - if (rights >-1) { - xdata->volume = (uint8)volume; - U16_TO_BE16((uint16)dir_id, xdata->dir_id); - U16_TO_BE16((uint16)searchsequenz, xdata->searchsequenz); - xdata->dir_rights = (uint8)rights; - data_len = sizeof(struct XDATA); - } else completition = (uint8) -rights; - } break; + case 0x3e : { /* FILE SEARCH INIT */ + /* returns dhandle for searchings */ + int dir_handle = (int)*requestdata; + int len = (int)*(requestdata+1); /* pathlen */ + uint8 *p = requestdata+2; /* path */ + struct XDATA { + uint8 volume; /* Volume */ + uint8 dir_id[2]; /* Direktory ID */ + uint8 searchsequence[2]; + uint8 dir_rights; /* Rights */ + } *xdata= (struct XDATA*) responsedata; + int volume; + int searchsequence; + int dir_id; + int rights = nw_open_dir_handle(dir_handle, p, len, + &volume, &dir_id, &searchsequence); + if (rights >-1) { + xdata->volume = (uint8)volume; + U16_TO_BE16((uint16)dir_id, xdata->dir_id); + U16_TO_BE16((uint16)searchsequence, xdata->searchsequence); + xdata->dir_rights = (uint8)rights; + data_len = sizeof(struct XDATA); + } else completition = (uint8) -rights; + } break; - case 0x3f : { /* file search continue */ - /* Dir_id is from file search init */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 volume; /* Volume ID */ - uint8 dir_id[2]; /* from File Search Init */ - uint8 searchsequence[2]; /* sequence FFFF = first entry */ - uint8 search_attrib; /* Attribute */ - /* 0 none, - 2 HIDDEN, - * 4 System , - 6 Both, - * 0x10 Dir - */ - uint8 len; /* fnname len */ - uint8 data[2]; /* fnname with wildcards */ - } *input = (struct INPUT *) ncprequest; - int len=input->len ; /* FN Length */ + case 0x3f : { /* file search continue */ + /* Dir_id is from file search init */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 volume; /* Volume ID */ + uint8 dir_id[2]; /* from File Search Init */ + uint8 searchsequence[2]; /* sequence FFFF = first entry */ + uint8 search_attrib; /* Attribute */ + /* 0 none, + 2 HIDDEN, + * 4 System , + 6 Both, + * 0x10 Dir + */ + uint8 len; /* fnname len */ + uint8 data[2]; /* fnname with wildcards */ + } *input = (struct INPUT *) ncprequest; + int len=input->len ; /* FN Length */ - struct XDATA { - uint8 searchsequence[2]; /* same as request sequence */ - uint8 dir_id[2]; /* Direktory ID */ - /* is correct !! */ - union { - NW_DIR_INFO d; - NW_FILE_INFO f; - } u; - } *xdata = (struct XDATA*)responsedata; + struct XDATA { + uint8 searchsequence[2]; /* same as request sequence */ + uint8 dir_id[2]; /* Direktory ID */ + /* is correct !! */ + union { + NW_DIR_INFO d; + NW_FILE_INFO f; + } u; + } *xdata = (struct XDATA*)responsedata; - int searchsequence = nw_dir_search( - (uint8*) &(xdata->u), - (int) GET_BE16(input->dir_id), - (int) GET_BE16(input->searchsequence), - (int) input->search_attrib, - input->data, len); - if (searchsequence > -1) { - U16_TO_BE16((uint16) searchsequence, xdata->searchsequence); - memcpy(xdata->dir_id, input->dir_id, 2); - data_len = sizeof(struct XDATA); - } else completition = (uint8) (- searchsequence); - } - break; + int searchsequence = nw_dir_search( + (uint8*) &(xdata->u), + (int) GET_BE16(input->dir_id), + (int) GET_BE16(input->searchsequence), + (int) input->search_attrib, + input->data, len); + if (searchsequence > -1) { + U16_TO_BE16((uint16) searchsequence, xdata->searchsequence); + memcpy(xdata->dir_id, input->dir_id, 2); + data_len = sizeof(struct XDATA); + } else completition = (uint8) (- searchsequence); + } + break; - case 0x40 : /* Search for a File */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 sequenz[2]; /* z.B. 0xff, 0xff */ - uint8 dir_handle; /* z.B 0x1 */ - uint8 search_attrib; /* z.B. 0x6 */ - uint8 len; - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 sequenz[2]; /* answer sequence */ - uint8 reserved[2]; /* z.B 0x0 0x0 */ - union { - NW_DIR_INFO d; - NW_FILE_INFO f; - } u; - } *xdata = (struct XDATA*)responsedata; - int len = input->len; - uint8 my_sequenz[2]; - int searchsequence; - uint32 owner; - memcpy(my_sequenz, input->sequenz, 2); - searchsequence = nw_search( (uint8*) &(xdata->u), - &owner, - (int)input->dir_handle, - (int) GET_BE16(my_sequenz), - (int) input->search_attrib, - input->data, len); - if (searchsequence > -1) { - U16_TO_BE16((uint16) searchsequence, xdata->sequenz); - data_len = sizeof(struct XDATA); - } else completition = (uint8) (- searchsequence); - } - break; + case 0x40 : /* Search for a File */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 sequence[2]; /* z.B. 0xff, 0xff */ + uint8 dir_handle; /* z.B 0x1 */ + uint8 search_attrib; /* z.B. 0x6 */ + uint8 len; + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 sequence[2]; /* answer sequence */ + uint8 reserved[2]; /* z.B 0x0 0x0 */ + union { + NW_DIR_INFO d; + NW_FILE_INFO f; + } u; + } *xdata = (struct XDATA*)responsedata; + int len = input->len; + uint8 my_sequence[2]; + int searchsequence; + uint32 owner; + memcpy(my_sequence, input->sequence, 2); + searchsequence = nw_search( (uint8*) &(xdata->u), + &owner, + (int)input->dir_handle, + (int) GET_BE16(my_sequence), + (int) input->search_attrib, + input->data, len); + if (searchsequence > -1) { + U16_TO_BE16((uint16) searchsequence, xdata->sequence); + data_len = sizeof(struct XDATA); + } else completition = (uint8) (- searchsequence); + } + break; - case 0x41 : { /* open file for reading */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 dirhandle; /* Dirhandle */ - uint8 attrib; /* z.B. 0x6 od. 0x4e */ - /* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */ - uint8 len; /* namelaenge */ - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* Dateihandle */ - uint8 reserve2[2]; /* z.B 0x0 0x0 */ - NW_FILE_INFO fileinfo; - } *xdata= (struct XDATA*)responsedata; - int fhandle=nw_creat_open_file((int)input->dirhandle, - input->data, input->len, - &(xdata->fileinfo), - (int)input->attrib, - 0x1, 0, (int)(ncprequest->task)); + case 0x41 : { /* open file for reading */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dirhandle; /* Dirhandle */ + uint8 attrib; /* z.B. 0x6 od. 0x4e */ + /* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */ + uint8 len; /* namelaenge */ + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* File Handle */ + uint8 reserved[2]; /* reserved by novell */ + NW_FILE_INFO fileinfo; + } *xdata= (struct XDATA*)responsedata; + int fhandle=nw_creat_open_file((int)input->dirhandle, + input->data, input->len, + &(xdata->fileinfo), + (int)input->attrib, + 0x1, /* read access */ + 0, + (int)(ncprequest->task)); - if (fhandle > -1){ - U32_TO_32(fhandle, xdata->fhandle); - U16_TO_BE16(0, xdata->ext_fhandle); - U16_TO_BE16(0, xdata->reserve2); - data_len = sizeof(struct XDATA); - } else completition = (uint8) (-fhandle); - } - break; + if (fhandle > -1){ + U32_TO_32(fhandle, xdata->fhandle); + xdata->ext_fhandle[0]=0; + xdata->ext_fhandle[1]=0; + xdata->reserved[0]=0; + xdata->reserved[1]=0; + data_len = sizeof(struct XDATA); + } else completition = (uint8) (-fhandle); + } + break; - case 0x42 : /* close file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 reserve; - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* filehandle */ - } *input = (struct INPUT *)ncprequest; - uint32 fhandle = GET_32(input->fhandle); - completition = (uint8)(-nw_close_file(fhandle, 0)); + case 0x42 : /* close file */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 reserve; + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* filehandle */ + } *input = (struct INPUT *)ncprequest; + uint32 fhandle = GET_32(input->fhandle); + completition = (uint8)(-nw_close_file(fhandle, + 0, (int)(ncprequest->task))); #if TEST_FNAME - if (!completition && fhandle == test_handle) { - do_druck++; - test_handle = -1; - } + if (!completition && fhandle == test_handle) { + do_druck++; + test_handle = -1; + } #endif - } - break; + } + break; - case 0x43 : /* creat file, overwrite if exist */ - case 0x4D : /* create new file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 dirhandle; - uint8 attribute; /* creat Attribute */ - uint8 len; - uint8 data[1]; /* Name */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 extfhandle[2]; - uint8 fhandle[4]; /* Filehandle */ - uint8 reserved[2]; /* rese. by NOVELL */ - NW_FILE_INFO fileinfo; - } *xdata= (struct XDATA*)responsedata; - int fhandle=nw_creat_open_file( - (int)input->dirhandle, - input->data, - (int)input->len, - &(xdata->fileinfo), - (int)input->attribute, - 0, - (function==0x43) ? 1 : 2, - (int)(ncprequest->task)); - if (fhandle > -1){ - data_len = sizeof(struct XDATA); - U32_TO_32 (fhandle, xdata->fhandle); - U16_TO_BE16(0, xdata->extfhandle); - U16_TO_BE16(0, xdata->reserved); + case 0x43 : /* creat file, overwrite if exist */ + case 0x4D : /* create new file */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dirhandle; + uint8 attribute; /* creat Attribute */ + uint8 len; + uint8 data[1]; /* Name */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 ext_fhandle[2]; + uint8 fhandle[4]; /* Filehandle */ + uint8 reserved[2]; /* reserved by NOVELL */ + NW_FILE_INFO fileinfo; + } *xdata= (struct XDATA*)responsedata; + int fhandle=nw_creat_open_file( + (int)input->dirhandle, + input->data, + (int)input->len, + &(xdata->fileinfo), + (int)input->attribute, + /* 0, 0x2, mst: 26-Sep-99 */ + 0x13, /* pcz: 14-Nov-99 */ + (function==0x43) ? 1 : 2, + (int)(ncprequest->task)); + if (fhandle > -1){ + data_len = sizeof(struct XDATA); + U32_TO_32 (fhandle, xdata->fhandle); + xdata->ext_fhandle[0]=0; + xdata->ext_fhandle[1]=0; + xdata->reserved[0]=0; + xdata->reserved[1]=0; #ifdef TEST_FNAME - input->data[input->len] = '\0'; - if (strstr(input->data, TEST_FNAME)){ - test_handle = fhandle; - do_druck++; - } + input->data[input->len] = '\0'; + if (strstr(input->data, TEST_FNAME)){ + test_handle = fhandle; + do_druck++; + } #endif - } else completition = (uint8) (-fhandle); - } - break; + } else completition = (uint8) (-fhandle); + } + break; - case 0x44 : /* file(s) delete */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 dirhandle; /* 0x0 */ - uint8 searchattributes; - /* 0 none, 2 Hidden, 4 System, 6 Both */ - uint8 len; - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - int err_code = nw_delete_datei((int)input->dirhandle, - input->data, (int)input->len); - if (err_code < 0) - completition = (uint8) -err_code; - } - break; + case 0x44 : /* file(s) delete */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dirhandle; /* 0x0 */ + uint8 searchattributes; + /* 0 none, 2 Hidden, 4 System, 6 Both */ + uint8 len; + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + int err_code = nw_delete_files((int)input->dirhandle, + (int)input->searchattributes, + input->data, (int)input->len); + if (err_code < 0) + completition = (uint8) -err_code; + } + break; - case 0x45 : /* rename file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 dir_handle; /* ?? 0x1 */ - uint8 reserve1; /* z.B. 0x2 */ - uint8 len; - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - uint8 *p = input->data+input->len; /* reserve z.B. 0x1 */ - /* + 1 = len2 */ - /* + 1 = data2 */ - int errcode = mv_file( - (int)input->dir_handle, input->data,(int)input->len, - (int)input->dir_handle, p+2, (int)*(p+1) ); + case 0x45 : /* rename file */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dir_handle; + uint8 searchattrib; + uint8 len; + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + uint8 *p = input->data+input->len; /* reserve z.B. 0x1 */ + /* + 1 = len2 */ + /* + 1 = data2 */ + int errcode = nw_mv_files( + (int)input->searchattrib, + (int)input->dir_handle, input->data,(int)input->len, + (int)input->dir_handle, p+2, (int)*(p+1) ); - if (errcode < 0) completition = (uint8) -errcode; - } - break; + if (errcode < 0) completition = (uint8) -errcode; + } + break; - case 0x46 : /* set file attributes */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 access; /* 0x80, od 0x0 */ - /* 0x80 for example is shared */ - uint8 dir_handle; - uint8 attrib; /* search attrib */ - uint8 len; - uint8 data[2]; /* filename */ - } *input = (struct INPUT *)ncprequest; - completition = - (uint8) (-nw_set_file_attributes((int)input->dir_handle, - input->data, (int)input->len, - (int)input->attrib, - (int)input->access)); - } - break; + case 0x46 : /* set file attributes */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 access; /* 0x80, od 0x0 */ + /* 0x80 for example is shared */ + uint8 dir_handle; + uint8 attrib; /* search attrib */ + uint8 len; + uint8 data[2]; /* filename */ + } *input = (struct INPUT *)ncprequest; + completition = + (uint8) (-nw_set_file_attributes((int)input->dir_handle, + input->data, (int)input->len, + (int)input->attrib, + (int)input->access)); + } + break; - case 0x47 : /* move pointer to end of file ???? */ - /* and return filesize ? */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 filler; - uint8 ext_filehandle[2]; /* all zero */ - uint8 fhandle[4]; /* Dateihandle */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 size[4]; /* Position ??? */ - } *xdata=(struct XDATA*)responsedata; - int fhandle = GET_32(input->fhandle); - int size = nw_seek_file(fhandle, 0); - if (size > -1) { - data_len = sizeof(struct XDATA); - U32_TO_BE32(size, xdata->size); - } - else completition = (uint8) -size; - } - break; + case 0x47 : /* move pointer to end of file ???? */ + /* and return filesize ? */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 filler; + uint8 ext_filehandle[2]; /* all zero */ + uint8 fhandle[4]; /* Dateihandle */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 size[4]; /* Position ??? */ + } *xdata=(struct XDATA*)responsedata; + int fhandle = GET_32(input->fhandle); + int size = nw_seek_file(fhandle, 0); + if (size > -1) { + data_len = sizeof(struct XDATA); + U32_TO_BE32(size, xdata->size); + } + else completition = (uint8) -size; + } + break; - case 0x48 : /* read file */ - { - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 filler; - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* filehandle */ - uint8 offset[4]; - uint8 max_size[2]; /* byte to readd */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 size[2]; /* read bytes */ - uint8 data[2]; /* read data */ - } *xdata=(struct XDATA*)responsedata; - int fhandle = GET_32 (input->fhandle); - int max_size = GET_BE16(input->max_size); - off_t offset = GET_BE32(input->offset); - int zusatz = (offset & 1) ? 1 : 0; - int size; - if (max_size > rw_buffer_size) { - XDPRINTF((1,0, "wanted read=%d byte > %d", - max_size, rw_buffer_size)); - size = -0x88; /* we say wrong filehandle */ - } else - size = nw_read_file(fhandle, - xdata->data+zusatz, - max_size, - offset); - if (size > -1) { - U16_TO_BE16(size, xdata->size); - data_len=size+zusatz+2; - } else completition = (uint8) -size; - } - break; + case 0x48 : /* read file */ + { + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 filler; + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* filehandle */ + uint8 offset[4]; + uint8 max_size[2]; /* byte to readd */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 size[2]; /* read bytes */ + uint8 data[2]; /* read data */ + } *xdata=(struct XDATA*)responsedata; + int fhandle = GET_32 (input->fhandle); + int max_size = GET_BE16(input->max_size); + off_t offset = GET_BE32(input->offset); + int zusatz = (offset & 1) ? 1 : 0; + int size; + if (max_size > rw_buffer_size) { + XDPRINTF((1,0, "wanted read=%d byte > %d", + max_size, rw_buffer_size)); + size = -0x88; /* we say wrong filehandle */ + } else + size = nw_read_file(fhandle, + xdata->data+zusatz, + max_size, + offset); + if (size > -1) { + U16_TO_BE16(size, xdata->size); + data_len=size+zusatz+2; + } else completition = (uint8) -size; + } + break; - case 0x49 : { /* write file */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 filler; /* 0 Filler ?? */ - uint8 ext_handle[2]; - uint8 fhandle[4]; /* Dateihandle */ - uint8 offset[4]; /* SEEK OFFSET */ - uint8 size[2]; /* Datasize */ - uint8 data[2]; /* Schreibdaten */ - } *input = (struct INPUT *)ncprequest; - off_t offset = GET_BE32(input->offset); - int fhandle = GET_32 (input->fhandle); - int input_size = GET_BE16(input->size); - int size = nw_write_file(fhandle, - input->data, - input_size, - offset); - if (size < 0) - completition = (uint8) -size; - else if (size < input_size) - completition = (uint8)0xff; - } - break; + case 0x49 : { /* write file */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 filler; /* 0 Filler ?? */ + uint8 ext_handle[2]; + uint8 fhandle[4]; /* Dateihandle */ + uint8 offset[4]; /* SEEK OFFSET */ + uint8 size[2]; /* Datasize */ + uint8 data[2]; /* Schreibdaten */ + } *input = (struct INPUT *)ncprequest; + off_t offset = GET_BE32(input->offset); + int fhandle = GET_32 (input->fhandle); + int input_size = GET_BE16(input->size); + int size = nw_write_file(fhandle, + input->data, + input_size, + offset); + if (size < 0) + completition = (uint8) -size; + else if (size < input_size) + completition = (uint8)0xff; + } + break; - case 0x4a : { /* File SERVER COPY */ - /* should be OK */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 reserved; /* Reserved by Novell */ - uint8 qext_fhandle[2]; /* ext Filehandle */ - uint8 qfhandle[4]; /* Quellfile */ - uint8 zext_fhandle[2]; /* ext Filehandle */ - uint8 zfhandle[4]; /* Zielfile */ - uint8 qoffset[4]; /* SourceFile Offset */ - uint8 zoffset[4]; /* DestFile Offset */ - uint8 size[4]; /* copysize */ - } *input = (struct INPUT *)ncprequest; - int qfhandle = GET_32 (input->qfhandle); - int zfhandle = GET_32 (input->zfhandle); - off_t qoffset = GET_BE32(input->qoffset); - off_t zoffset = GET_BE32(input->zoffset); - uint32 input_size = GET_BE32(input->size); - int size = nw_server_copy(qfhandle, qoffset, - zfhandle, zoffset, - input_size); - if (size < 0) completition = (uint8) -size; - else { - struct XDATA { - uint8 zsize[4]; /* real transfered Bytes */ - } *xdata= (struct XDATA*)responsedata; - U32_TO_BE32(size, xdata->zsize); - data_len = sizeof(struct XDATA); - } - } - break; + case 0x4a : { /* File SERVER COPY */ + /* should be OK */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 reserved; /* Reserved by Novell */ + uint8 qext_fhandle[2]; /* ext Filehandle */ + uint8 qfhandle[4]; /* Quellfile */ + uint8 zext_fhandle[2]; /* ext Filehandle */ + uint8 zfhandle[4]; /* Zielfile */ + uint8 qoffset[4]; /* SourceFile Offset */ + uint8 zoffset[4]; /* DestFile Offset */ + uint8 size[4]; /* copysize */ + } *input = (struct INPUT *)ncprequest; + int qfhandle = GET_32 (input->qfhandle); + int zfhandle = GET_32 (input->zfhandle); + off_t qoffset = GET_BE32(input->qoffset); + off_t zoffset = GET_BE32(input->zoffset); + uint32 input_size = GET_BE32(input->size); + int size = nw_server_copy(qfhandle, qoffset, + zfhandle, zoffset, + input_size); + if (size < 0) completition = (uint8) -size; + else { + struct XDATA { + uint8 zsize[4]; /* real transfered Bytes */ + } *xdata= (struct XDATA*)responsedata; + U32_TO_BE32(size, xdata->zsize); + data_len = sizeof(struct XDATA); + } + } + break; - case 0x4b : { /* set date of file, file will be closed later */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 filler; - uint8 reserve[2]; /* ext Filehandle */ - uint8 fhandle[4]; /* Dateihandle */ - uint8 zeit[2]; /* time */ - uint8 datum[2]; /* date */ - } *input = (struct INPUT *)ncprequest; - int result = nw_set_fdate_time(GET_32(input->fhandle), - input->datum, input->zeit); - if (result <0) completition = (uint8) -result; - } - break; + case 0x4b : { /* set date of file, file will be closed later */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 filler; + uint8 reserve[2]; /* ext Filehandle */ + uint8 fhandle[4]; /* Dateihandle */ + uint8 zeit[2]; /* time */ + uint8 datum[2]; /* date */ + } *input = (struct INPUT *)ncprequest; + int result = nw_set_fdate_time(GET_32(input->fhandle), + input->datum, input->zeit); + if (result <0) completition = (uint8) -result; + } + break; - case 0x4c : { /* open file */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 dirhandle; /* Dirhandle */ - uint8 attrib; /* z.B. 0x6 od. 0x4e */ - /* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */ + case 0x4c : { /* open file */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 dirhandle; /* Dirhandle */ + uint8 attrib; /* z.B. 0x6 od. 0x4e */ + /* O_RDWR|TRUNC 0x6, O_RDONLY 0x6 */ - uint8 access; /* z.B. 0x9 od 0x11 od. 0x13 */ - /* O_RDWR|TRUNC 0x13, O_RDONLY 0x11 */ - /* O_RDWR|TRUNC|O_DENYNONE 0x3 */ - /* 0x10 BINAERMODUS ?? */ - /* 0x02 do write */ - uint8 len; /* namelaenge */ - uint8 data[2]; /* Name */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 ext_fhandle[2]; /* all zero */ - uint8 fhandle[4]; /* Dateihandle */ - uint8 reserve2[2]; /* z.B 0x0 0x0 */ - NW_FILE_INFO fileinfo; - } *xdata= (struct XDATA*)responsedata; - int fhandle=nw_creat_open_file((int)input->dirhandle, - input->data, input->len, - &(xdata->fileinfo), - (int)input->attrib, - (int)input->access, 0, - (int)(ncprequest->task)); + uint8 access; /* z.B. 0x9 od 0x11 od. 0x13 */ + /* O_RDWR|TRUNC 0x13, O_RDONLY 0x11 */ + /* O_RDWR|TRUNC|O_DENYNONE 0x3 */ + /* 0x10 BINAERMODUS ?? */ + /* 0x02 do write */ + uint8 len; /* namelaenge */ + uint8 data[2]; /* Name */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 ext_fhandle[2]; /* all zero */ + uint8 fhandle[4]; /* Dateihandle */ + uint8 reserved[2]; /* reserved by Novell */ + NW_FILE_INFO fileinfo; + } *xdata= (struct XDATA*)responsedata; + int fhandle=nw_creat_open_file((int)input->dirhandle, + input->data, input->len, + &(xdata->fileinfo), + (int)input->attrib, + (int)input->access, 0, + (int)(ncprequest->task)); - if (fhandle > -1){ - U32_TO_32 (fhandle, xdata->fhandle); - U16_TO_BE16(0, xdata->ext_fhandle); - U16_TO_BE16(0, xdata->reserve2); - - data_len = sizeof(struct XDATA); + if (fhandle > -1){ + U32_TO_32 (fhandle, xdata->fhandle); + xdata->ext_fhandle[0]=0; + xdata->ext_fhandle[1]=0; + xdata->reserved[0]=0; + xdata->reserved[1]=0; + data_len = sizeof(struct XDATA); #ifdef TEST_FNAME - input->data[input->len] = '\0'; - if (strstr(input->data, TEST_FNAME)){ - test_handle = fhandle; - do_druck++; - } + input->data[input->len] = '\0'; + if (strstr(input->data, TEST_FNAME)){ + test_handle = fhandle; + do_druck++; + } #endif - } else completition = (uint8) (-fhandle); - } - break; + } else completition = (uint8) (-fhandle); + } + break; #if WITH_NAME_SPACE_CALLS - case 0x56 : /* some extended atrribute calls */ - { - int result = handle_func_0x56(requestdata, responsedata, ncprequest->task); - if (result > -1) data_len = result; - else completition=(uint8)-result; - } - break; + case 0x56 : /* some extended atrribute calls */ + { + int result = handle_func_0x56(requestdata, responsedata, ncprequest->task); + if (result > -1) data_len = result; + else completition=(uint8)-result; + } + break; - case 0x57 : /* some new namespace calls */ - { - int result = handle_func_0x57(requestdata, responsedata, ncprequest->task); - if (result > -1) data_len = result; - else completition=(uint8)-result; - } - break; + case 0x57 : /* some new namespace calls */ + { + int result = handle_func_0x57(requestdata, responsedata, ncprequest->task); + if (result > -1) data_len = result; + else completition=(uint8)-result; + } + break; #endif #ifdef _MAR_TESTS_XX - case 0x5f : { /* ????????????? UNIX Client */ - /* a 4.1 Server also do not know this call */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 unknown[4]; /* 0x10, 0,0,0 */ - } *input = (struct INPUT *)ncprequest; - completition = 0; - } - break; + case 0x5f : { /* ????????????? UNIX Client */ + /* a 4.1 Server also do not know this call */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 unknown[4]; /* 0x10, 0,0,0 */ + } *input = (struct INPUT *)ncprequest; + completition = 0; + } + break; #endif - case 0x61 : + case 0x61 : #if ENABLE_BURSTMODE - if (server_version_flags&1) { /* enable Burstmode */ - /* Negotiate Buffer Size, Packetsize new ? */ - int wantsize = GET_BE16((uint8*)requestdata); - /* wantsize is here max. - * phys. packet size without MAC-header - * e.g. 1500 if ethernet - */ - int flags = (int) *(requestdata+2); - /**** flags *********************** - * CHECKSUMMING_REQUESTED 1 - * SIGNATURE_REQUESTED 2 - * COMPLETE_SIGNATURES_REQUESTED 4 - * ENCRYPTION_REQUESTED 8 - * LIP_DISABLED 0x80 - **********************************/ - struct XDATA { - uint8 getsize[2]; - uint8 socket[2]; /* echo socket */ - uint8 flags; /* zero */ - } *xdata= (struct XDATA*)responsedata; - memset(xdata, 0, sizeof(*xdata)); - wantsize = min(IPX_MAX_DATA+30, wantsize); - rw_buffer_size = min(RW_BUFFERSIZE, wantsize-64); + if (server_version_flags&1) { /* enable Burstmode */ + /* Negotiate Buffer Size, Packetsize new ? */ + int wantsize = GET_BE16((uint8*)requestdata); + /* wantsize is here max. + * phys. packet size without MAC-header + * e.g. 1500 if ethernet + */ + int flags = (int) *(requestdata+2); + /**** flags *********************** + * CHECKSUMMING_REQUESTED 1 + * SIGNATURE_REQUESTED 2 + * COMPLETE_SIGNATURES_REQUESTED 4 + * ENCRYPTION_REQUESTED 8 + * LIP_DISABLED 0x80 + **********************************/ + struct XDATA { + uint8 getsize[2]; + uint8 socket[2]; /* echo socket */ + uint8 flags; /* zero */ + } *xdata= (struct XDATA*)responsedata; + memset(xdata, 0, sizeof(*xdata)); + wantsize = min(IPX_MAX_DATA+30, wantsize); + rw_buffer_size = min(RW_BUFFERSIZE, wantsize-64); - U16_TO_BE16(wantsize, xdata->getsize); - U16_TO_BE16(sock_echo, xdata->socket); - data_len = sizeof(*xdata); - XDPRINTF((5,0, "Negotiate Buffer (new) =0x%04x,(%d), flags=0x%x", - (int) wantsize, (int) wantsize, flags)); - } else + U16_TO_BE16(wantsize, xdata->getsize); + U16_TO_BE16(sock_echo, xdata->socket); + data_len = sizeof(*xdata); + XDPRINTF((5,0, "Negotiate Buffer (new) =0x%04x,(%d), flags=0x%x", + (int) wantsize, (int) wantsize, flags)); + } else #endif - { - XDPRINTF((2,0, "Function '0x61' (Burst) not enabled")); - completition = 0xfb; /* unknown request */ - nw_debug=0; - } - break; + { + XDPRINTF((2,0, "Function '0x61' (Burst) not enabled")); + completition = 0xfb; /* unknown request */ + nw_debug=0; + } + break; - case 0x65 : /* Packet Burst Connection Request */ + case 0x65 : /* Packet Burst Connection Request */ #if ENABLE_BURSTMODE - if (server_version_flags&1) { /* enable burstmode */ - struct INPUT { - uint8 header[7]; /* Requestheader */ - uint8 connid[4]; /* RANDOM ID */ - /* build by time() */ - uint8 max_packet_size[4]; /* HI-LO */ - /* max_packet_size is here max. - * phys. packet size without MAC-header - * e.g. 1500 if ethernet - */ - uint8 target_socket[2]; /* HI-LO */ - uint8 max_send_size[4]; /* HI-LO */ - uint8 max_recv_size[4]; /* HI-LO */ - } *input = (struct INPUT *)ncprequest; - struct XDATA { - uint8 server_id[4]; /* RANDOM ID */ - /* build by time() */ - uint8 max_packet_size[4]; /* HI-LO */ - uint8 max_send_size[4]; /* HI-LO */ - uint8 max_recv_size[4]; /* HI-LO */ - } *xdata= (struct XDATA*) responsedata; - int client_socket=GET_BE16(input->target_socket); - uint32 max_packet_size=min(sizeof(IPX_DATA), - GET_BE32(input->max_packet_size)-30); - U32_TO_BE32(max_packet_size + 30, - xdata->max_packet_size); - if (!burst_w) - burst_w=(BURST_W*)xcmalloc(sizeof(BURST_W)); - xfree(burst_w->sendburst); - xfree(burst_w->send_buf); - xfree(burst_w->recv_buf); + if (server_version_flags&1) { /* enable burstmode */ + struct INPUT { + uint8 header[7]; /* Requestheader */ + uint8 connid[4]; /* RANDOM ID */ + /* build by time() */ + uint8 max_packet_size[4]; /* HI-LO */ + /* max_packet_size is here max. + * phys. packet size without MAC-header + * e.g. 1500 if ethernet + */ + uint8 target_socket[2]; /* HI-LO */ + uint8 max_send_size[4]; /* HI-LO */ + uint8 max_recv_size[4]; /* HI-LO */ + } *input = (struct INPUT *)ncprequest; + struct XDATA { + uint8 server_id[4]; /* RANDOM ID */ + /* build by time() */ + uint8 max_packet_size[4]; /* HI-LO */ + uint8 max_send_size[4]; /* HI-LO */ + uint8 max_recv_size[4]; /* HI-LO */ + } *xdata= (struct XDATA*) responsedata; + int client_socket=GET_BE16(input->target_socket); + uint32 max_packet_size=min(sizeof(IPX_DATA), + GET_BE32(input->max_packet_size)-30); + U32_TO_BE32(max_packet_size + 30, + xdata->max_packet_size); + if (!burst_w) + burst_w=(BURST_W*)xcmalloc(sizeof(BURST_W)); + xfree(burst_w->sendburst); + xfree(burst_w->send_buf); + xfree(burst_w->recv_buf); - burst_w->max_burst_data_size= - max_packet_size-sizeof(BURSTPACKET); + burst_w->max_burst_data_size= + max_packet_size-sizeof(BURSTPACKET); - burst_w->sendburst= - (BURSTPACKET*)xcmalloc(max_packet_size); + burst_w->sendburst= + (BURSTPACKET*)xcmalloc(max_packet_size); - burst_w->ud.udata.buf = (char*)(burst_w->sendburst); + burst_w->ud.udata.buf = (char*)(burst_w->sendburst); - burst_w->sendburst->type[0]=0x77; - burst_w->sendburst->type[1]=0x77; - burst_w->sendburst->streamtyp=2; /* BIG_SEND_BURST */ + burst_w->sendburst->type[0]=0x77; + burst_w->sendburst->type[1]=0x77; + burst_w->sendburst->streamtyp=2; /* BIG_SEND_BURST */ - U32_TO_BE32(time(NULL), burst_w->sendburst->source_conn); - U16_TO_16(act_connection, burst_w->sendburst->source_conn); - /* we need to identify it */ + U32_TO_BE32(time(NULL), burst_w->sendburst->source_conn); + U16_TO_16(act_connection, burst_w->sendburst->source_conn); + /* we need to identify it */ - memcpy(xdata->server_id, - burst_w->sendburst->source_conn, 4); - memcpy(burst_w->sendburst->dest_conn, - input->connid, 4); + memcpy(xdata->server_id, + burst_w->sendburst->source_conn, 4); + memcpy(burst_w->sendburst->dest_conn, + input->connid, 4); - burst_w->max_send_size= - min(max_burst_send_size, - GET_BE32(input->max_recv_size)); - burst_w->send_buf=xcmalloc(burst_w->max_send_size+8); + burst_w->max_send_size= + min(max_burst_send_size, + GET_BE32(input->max_recv_size)); + burst_w->send_buf=xcmalloc(burst_w->max_send_size+8); - burst_w->max_recv_size= - min(max_burst_recv_size, - GET_BE32(input->max_send_size)); + burst_w->max_recv_size= + min(max_burst_recv_size, + GET_BE32(input->max_send_size)); #if 1 /* MUST BE REMOVED LATER !!! */ - /* we don't want fragmented receive packets */ - if (burst_w->max_recv_size > - burst_w->max_burst_data_size-24) - burst_w->max_recv_size - =burst_w->max_burst_data_size-24; + /* we don't want fragmented receive packets */ + if (burst_w->max_recv_size > + burst_w->max_burst_data_size-24) + burst_w->max_recv_size + =burst_w->max_burst_data_size-24; #endif - burst_w->recv_buf=xcmalloc(burst_w->max_recv_size+24); + burst_w->recv_buf=xcmalloc(burst_w->max_recv_size+24); #if 1 - U32_TO_BE32(0x5ff22, burst_w->sendburst->delaytime); + U32_TO_BE32(0x5ff22, burst_w->sendburst->delaytime); #endif - U32_TO_BE32(burst_w->max_recv_size, xdata->max_recv_size); - U32_TO_BE32(burst_w->max_send_size, xdata->max_send_size); + U32_TO_BE32(burst_w->max_recv_size, xdata->max_recv_size); + U32_TO_BE32(burst_w->max_send_size, xdata->max_send_size); - burst_w->ipx_pack_typ = PACKT_CORE; - burst_w->ud.opt.len = sizeof(uint8); - burst_w->ud.opt.maxlen = sizeof(uint8); - burst_w->ud.opt.buf = (char*)&(burst_w->ipx_pack_typ); + burst_w->ipx_pack_typ = PACKT_CORE; + burst_w->ud.opt.len = sizeof(uint8); + burst_w->ud.opt.maxlen = sizeof(uint8); + burst_w->ud.opt.buf = (char*)&(burst_w->ipx_pack_typ); - memcpy(&(burst_w->to_addr), &from_addr, sizeof(ipxAddr_t)); - U16_TO_BE16(client_socket, burst_w->to_addr.sock); - burst_w->ud.addr.len = sizeof(ipxAddr_t); - burst_w->ud.addr.maxlen = sizeof(ipxAddr_t); - burst_w->ud.addr.buf = (char*)&(burst_w->to_addr); - data_len = sizeof(*xdata); - } else + memcpy(&(burst_w->to_addr), &from_addr, sizeof(ipxAddr_t)); + U16_TO_BE16(client_socket, burst_w->to_addr.sock); + burst_w->ud.addr.len = sizeof(ipxAddr_t); + burst_w->ud.addr.maxlen = sizeof(ipxAddr_t); + burst_w->ud.addr.buf = (char*)&(burst_w->to_addr); + data_len = sizeof(*xdata); + } else #endif - { - XDPRINTF((2,0, "Packet Burst Connection Request not enabled")); - nw_debug=0; - completition = 0xfb; /* unknown request */ - } - break; + { + XDPRINTF((2,0, "Packet Burst Connection Request not enabled")); + nw_debug=0; + completition = 0xfb; /* unknown request */ + } + break; - case 0x68 : /* NDS NCP, NDS Fragger Protokoll ?? */ - XDPRINTF((2,0, "NDS Fragger Protokoll not supportet")); - nw_debug=0; - completition = 0xfb; /* unknown request */ - break; + case 0x68 : /* NDS NCP, NDS Fragger Protokoll ?? */ + XDPRINTF((2,0, "NDS Fragger Protokoll not supportet")); + nw_debug=0; + completition = 0xfb; /* unknown request */ + break; - default : completition = 0xfb; /* unknown request */ - break; + default : completition = 0xfb; /* unknown request */ + break; } /* switch function */ + } else if (ncp_type == 0x1111) { free_queue_jobs(); (void) nw_init_connect(); @@ -1781,7 +2177,7 @@ NWCONN 1:len 15, DATA:,0x5,0x1,0x0,0x12,0xa,'0','9','0','6', if (nw_debug && (completition == 0xfb || (do_druck == 1))) { /* UNKWON FUNCTION od. TYPE */ pr_debug_request(); if (completition == 0xfb) - XDPRINTF((0,0, "UNKNOWN FUNCTION od. TYPE: 0x%x", function)); + XDPRINTF((0,0, "UNKNOWN FUNCTION or TYPE: 0x%x", function)); else if (data_len){ int j = data_len; uint8 *p = responsedata; @@ -1890,22 +2286,24 @@ static void handle_after_bind() switch (ufunc) { case 0x14: /* Login Objekt, unencrypted passwords */ case 0x18: { /* crypt_keyed LOGIN */ - int fnlen = (int) *(bindresponse + 3 * sizeof(int)); + int grpcount = * (int*)(bindresponse + 4 * sizeof(int)); + uint32 *grps = (uint32*)(bindresponse + 5 * sizeof(int)); + int unxloginlen = (int)*(uint8*)(grps+grpcount); + uint8 *unxloginname = (uint8*)(grps+grpcount)+1; uint8 objname[48]; /* ncpserv have changed the structure */ - if (ufunc==0x14) { xstrmaxcpy(objname, requestdata+6, (int) *(requestdata+5)); } else if (ufunc==0x18){ xstrmaxcpy(objname, requestdata+14, (int) *(requestdata+13)); } else objname[0]='\0'; - - set_nw_user(*((int*)bindresponse), /* gid */ + set_nw_user(*((int*)bindresponse), /* gid */ *((int*)(bindresponse+sizeof(int))), /* uid */ - *((uint32*)(bindresponse + 2 * sizeof(int))), /* id */ + *((int*)(bindresponse + 2 * sizeof(int))), /* id_flags */ + *((uint32*)(bindresponse + 3 * sizeof(int))), /* id */ objname, /* login name */ - fnlen, /* unix homepathlen */ - bindresponse + 3 * sizeof(int) +1); /* unix homepath */ + unxloginlen, unxloginname, + grpcount, grps); } break; @@ -1921,7 +2319,8 @@ static void handle_after_bind() } *input = (struct INPUT *) (ncprequest); uint32 q_id = GET_BE32(input->queue_id); uint8 *qjob = bindresponse; - int result = creat_queue_job(q_id, qjob, + int result = creat_queue_job( (int) ncprequest->task, + q_id, qjob, responsedata, (ufunc == 0x68) ); if (result > -1) @@ -1969,7 +2368,8 @@ static void handle_after_bind() } *input = (struct INPUT *) (ncprequest); uint32 q_id = GET_BE32(input->queue_id); uint8 *qjob = bindresponse; - int result = service_queue_job(q_id, qjob, + int result = service_queue_job((int)ncprequest->task, + q_id, qjob, responsedata, ufunc==0x71); if (result > -1) @@ -2141,11 +2541,17 @@ static void close_all(void) } static int fl_get_int=0; +/* signals + * &01 sig_quit + * &02 sig_hup + * &04 sig_usr1 + * &08 sig_usr2 + */ static void sig_quit(int rsig) { XDPRINTF((2, 0, "Got Signal=%d", rsig)); - fl_get_int=-1; + fl_get_int |= 1; } static void sig_pipe(int rsig) @@ -2156,14 +2562,48 @@ static void sig_pipe(int rsig) static void sig_hup(int rsig) { - if (!fl_get_int) fl_get_int=1; + fl_get_int |= 2; signal(SIGHUP, sig_hup); } +static void sig_usr1(int rsig) +{ + fl_get_int |= 4; +} + +static void sig_usr2(int rsig) +{ + fl_get_int |= 8; +} + static void get_new_debug(void) { get_ini_debug(3); - if (fl_get_int > 0) fl_get_int=0; + fl_get_int &= ~2; +} + +static void handle_extern_command(void) +{ + fl_get_int &= ~4; + signal(SIGUSR1, sig_usr1); +} + +static void handle_sigusr2(void) +{ + char fn[256]; + FILE *f; + fl_get_int &= ~8; + sprintf(fn, "/tmp/nwconn%04d.log", act_connection); + seteuid(0); + unlink(fn); /* security: mst:18-Apr-00 */ + f=fopen(fn, "w"); + reseteuid(); + if (f) { + log_file_module(f); + fclose(f); + } else + errorp(0, "handle_sigusr2", "cannot open %s for writing", fn); + signal(SIGUSR2, sig_usr2); } static void set_sig(void) @@ -2173,6 +2613,8 @@ static void set_sig(void) signal(SIGINT, sig_quit); signal(SIGPIPE, sig_pipe); signal(SIGHUP, sig_hup); + signal(SIGUSR1, sig_usr1); + signal(SIGUSR2, sig_usr2); if (use_mmap) signal(SIGBUS, sig_bus_mmap); /* in nwfile.c */ } @@ -2190,9 +2632,9 @@ int main(int argc, char **argv) setuid(0); setgid(0); act_connection = atoi(*(argv+1)); - init_tools(NWCONN, act_connection); + init_tools(NWCONN, 0); memset(saved_readbuff, 0, sizeof(saved_readbuff)); - XDPRINTF((2, 0, "FATHER PID=%d, ADDR=%s CON:%d", + XDPRINTF((3, 0, "FATHER PID=%d, ADDR=%s CON:%d", father_pid, *(argv+2), act_connection)); adr_to_ipx_addr(&from_addr, *(argv+2)); @@ -2211,7 +2653,7 @@ int main(int argc, char **argv) { int conn = act_connection; int result = ioctl(0, SIOCIPXNCPCONN, &conn); - XDPRINTF((2, 0, "ioctl:SIOCIPXNCPCONN result=%d", result)); + XDPRINTF((3, 0, "ioctl:SIOCIPXNCPCONN result=%d", result)); } # endif # endif @@ -2236,7 +2678,7 @@ int main(int argc, char **argv) set_sig(); - while (fl_get_int >= 0) { + while ( !(fl_get_int&1) ) { int data_len = read(0, readbuff, sizeof(readbuff)); /* this read is a pipe or a socket read, @@ -2244,8 +2686,13 @@ int main(int argc, char **argv) */ if (fl_get_int) { - if (fl_get_int == 1) get_new_debug(); - else if (fl_get_int < 0) break; + if (fl_get_int & 1) break; + if (fl_get_int & 2) + get_new_debug(); + if (fl_get_int & 4) + handle_extern_command(); + if (fl_get_int & 8) + handle_sigusr2(); } if (data_len > 0) { @@ -2274,7 +2721,8 @@ int main(int argc, char **argv) } saved_sequence = -1; } else { /* this calls I must handle, it is a request */ - time_t act_time=time(NULL); + act_time=time(NULL); + act_ncpsequence=(int)(ncprequest->sequence); if (act_time > last_time+300 && saved_sequence == -1) { /* ca. 5 min. reset wdogs */ @@ -2288,7 +2736,11 @@ int main(int argc, char **argv) handle_burst((BURSTPACKET*)readbuff, data_len); } else #endif - { + else if (ncp_type == 0x2121) { /* request from nwbind */ + /* mst:25-Apr-00 */ + requestlen = data_len - sizeof(NCPREQUEST); + handle_nwbind_request(); + } else { int result; requestlen = data_len - sizeof(NCPREQUEST); if (0 != (result = handle_ncp_serv()) ) { @@ -2316,6 +2768,6 @@ int main(int argc, char **argv) } # endif close_all(); - XDPRINTF((2,0, "leave nwconn pid=%d", getpid())); + XDPRINTF((3,0, "leave nwconn pid=%d", getpid())); return(0); } diff --git a/nwconn.h b/nwconn.h index 6a1cbaf..58aa6b6 100644 --- a/nwconn.h +++ b/nwconn.h @@ -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 diff --git a/nwdbm.c b/nwdbm.c index 2435859..31886ef 100644 --- a/nwdbm.c +++ b/nwdbm.c @@ -1,5 +1,5 @@ -/* nwdbm.c 01-Nov-97 data base for mars_nwe */ -/* (C)opyright (C) 1993,1995 Martin Stover, Marburg, Germany +/* nwdbm.c 25-Apr-00 data base for mars_nwe */ +/* (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 @@ -16,16 +16,23 @@ * 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: removed bug from pl18 for passwords beginning with '-' + * + */ + /* * This code is only called from the process 'nwbind' * So, there is no need for locking or something else. */ - #include "net.h" #include "nwdbm.h" #include "nwcrypt.h" #include "nwqueue.h" #include "dirent.h" +#include "unxfile.h" #ifdef LINUX # ifdef USE_GDBM @@ -44,7 +51,7 @@ #endif #ifdef USE_GDBM -# define DBM_FILE GDBM_FILE +# define DBM_FILE GDBM_FILE #else # define DBM_FILE DBM * #endif @@ -59,13 +66,16 @@ int tells_server_version=1; /* default 1 since 12-Jan-97 */ int password_scheme=0; uint8 *sys_unixname=NULL; /* Unixname of SYS: ends with '/' */ -int sys_unixnamlen=0; /* len of unixname */ -int sys_downshift=0; /* is SYS downshift */ +int sys_unixnamlen=0; /* len of unixname */ +int sys_downshift=0; /* is SYS downshift */ +int sys_has_trustee=0; /* has SYS trustees ? */ uint8 *sys_sysname=NULL; /* Name of first Volume, normally SYS */ uint32 network_serial_nmbr=(uint32)NETWORK_SERIAL_NMBR; uint16 network_appl_nmbr=(uint16)NETWORK_APPL_NMBR; -static int entry8_flags = 0; +int entry8_flags = 0; /* used in nwbind too */ + +static int entry17_flags = 0; static datum key; static datum data; @@ -95,33 +105,55 @@ static DBM_FILE my_dbms[COUNT_DBM_FILES] = { }; #endif -static int x_dbminit(char *s) +static int x_dbminit(char *s, int ro) { char buff[256]; #ifdef USE_GDBM (void)get_div_pathes(buff, s, 1, ".pag"); - my_dbm = gdbm_open(buff, 0, GDBM_WRCREAT, 0600, NULL); + my_dbm = gdbm_open(buff, 0, ro ? GDBM_READER : GDBM_WRCREAT, 0600, NULL); #else (void)get_div_pathes(buff, s, 1, NULL); - my_dbm = dbm_open(buff, O_RDWR|O_CREAT, 0600); + my_dbm = dbm_open(buff, ro ? O_RDONLY : O_RDWR|O_CREAT , 0600); #endif return( (my_dbm == NULL) ? -1 : 0); } static int dbminit(int what_dbm) { -#if DBM_REMAINS_OPEN int result = 0; +#if DBM_REMAINS_OPEN if (NULL == my_dbms[what_dbm]) { - result = x_dbminit(dbm_fn[what_dbm]); + result = x_dbminit(dbm_fn[what_dbm], 0); if (!result) my_dbms[what_dbm] = my_dbm; } else my_dbm = my_dbms[what_dbm]; return(result); #else - return(x_dbminit(dbm_fn[what_dbm])); + return(x_dbminit(dbm_fn[what_dbm], 0)); #endif + if (result) + errorp(0, "dbminit", "on %s", dbm_fn[what_dbm]); + return(result); } +static int dbminit_ro(int what_dbm) +{ + int result = 0; +#if DBM_REMAINS_OPEN + if (NULL == my_dbms[what_dbm]) { + result = x_dbminit(dbm_fn[what_dbm], 1); + if (!result) my_dbms[what_dbm] = my_dbm; + } else my_dbm = my_dbms[what_dbm]; + return(result); +#else + return(x_dbminit(dbm_fn[what_dbm], 1)); +#endif + if (result) + errorp(0, "dbminit ro", "on %s", dbm_fn[what_dbm]); + return(result); +} + + + static int dbmclose() { if (my_dbm != NULL) { @@ -141,6 +173,7 @@ void sync_dbm() { #if DBM_REMAINS_OPEN int k = COUNT_DBM_FILES; + dbmclose(); while (k--) { if (NULL != my_dbms[k]) { # ifdef USE_GDBM @@ -151,10 +184,11 @@ void sync_dbm() my_dbms[k] = NULL; } } +#else + dbmclose(); #endif } - #ifdef USE_GDBM static datum firstkey(void) { @@ -182,6 +216,7 @@ static datum fetch(datum key) last_dptr=result.dptr; return(result); } + # define delete(key) gdbm_delete(my_dbm, key) # define store(key, content) gdbm_store(my_dbm, key, content, GDBM_REPLACE) #else @@ -288,32 +323,32 @@ int scan_for_obj(NETOBJ *o, uint32 last_obj_id, int ignore_rights) { int result = -0xfc; /* no Object */ XDPRINTF((2, 0,"scan_for_obj OBJ=%s, type=0x%x, lastid=0x%x", - o->name, (int)o->type, (int)last_obj_id)); + o->name, (int)o->type, (int)last_obj_id)); if (!dbminit(FNOBJ)){ key = firstkey(); if (last_obj_id && (last_obj_id != MAX_U32)){ int flag = 0; while (key.dptr != NULL && !flag) { - if ( ((NETOBJ*)(key.dptr))->id == last_obj_id) flag++; - key = nextkey(key); + if ( ((NETOBJ*)(key.dptr))->id == last_obj_id) flag++; + key = nextkey(key); } } while (key.dptr != NULL && result) { data = fetch(key); if (data.dptr != NULL){ - NETOBJ *obj = (NETOBJ*)data.dptr; - if ( ( ((int)obj->type == (int)o->type) || o->type == MAX_U16) && - name_match(obj->name, o->name) && + NETOBJ *obj = (NETOBJ*)data.dptr; + if ( ( ((int)obj->type == (int)o->type) || o->type == MAX_U16) && + name_match(obj->name, o->name) && ( ignore_rights || - (b_acc(obj->id, obj->security, 0x00)== 0))) { - XDPRINTF((2, 0, "found OBJ=%s, id=0x%x", obj->name, (int)obj->id)); - result = 0; - memcpy((char *)o, (char*)obj, sizeof(NETOBJ)); - } else { - XDPRINTF((3,0,"not found,but NAME=%s, type=0x%x, id=0x%x", - obj->name, (int)obj->type, (int)obj->id)); - } + (b_acc(obj->id, obj->security, 0x00)== 0))) { + XDPRINTF((2, 0, "found OBJ=%s, id=0x%x", obj->name, (int)obj->id)); + result = 0; + memcpy((char *)o, (char*)obj, sizeof(NETOBJ)); + } else { + XDPRINTF((3,0,"not found,but NAME=%s, type=0x%x, id=0x%x", + obj->name, (int)obj->type, (int)obj->id)); + } } if (result) key = nextkey(key); } /* while */ @@ -336,18 +371,18 @@ static int loc_delete_property(uint32 obj_id, XDPRINTF((2,0, "loc_delete_property obj_id=0x%x, prop=%s", obj_id, prop_name)); if (!dbminit(FNPROP)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { - NETPROP *p=(NETPROP*)key.dptr; - if (p->obj_id == obj_id) { - data = fetch(key); - p = (NETPROP*)data.dptr; + NETPROP *p=(NETPROP*)key.dptr; + if (p->obj_id == obj_id) { + data = fetch(key); + p = (NETPROP*)data.dptr; if (p != NULL && name_match(p->name, prop_name)){ - XDPRINTF((2,0, "found prop: %s, id=%d for deleting", p->name, (int)p->id)); + XDPRINTF((2,0, "found prop: %s, id=%d for deleting", p->name, (int)p->id)); if (ever || !b_acc(obj_id, p->security, 0x13)) { - if ((int)(p->id) > result) result = (int)(p->id); - xset[p->id]++; + if ((int)(p->id) > result) result = (int)(p->id); + xset[p->id]++; } else if (result < 0) result = -0xf6; /* no delete priv. */ - } - } + } + } } /* for */ } else result = -0xff; dbmclose(); @@ -364,34 +399,34 @@ static int loc_delete_property(uint32 obj_id, key.dsize = NETVAL_KEY_SIZE; val.obj_id = obj_id; for (k = 1; k <= result; k++){ - if (xset[k]){ - int l = 0; - val.prop_id = (uint8)k; - while (l++ < 255) { - val.segment = (uint8)l; - if (delete(key)) break; - } - } + if (xset[k]){ + int l = 0; + val.prop_id = (uint8)k; + while (l++ < 255) { + val.segment = (uint8)l; + if (delete(key)) break; + } + } } /* for */ } else result=-0xff; dbmclose(); if (result > 0) { if (!dbminit(FNPROP)){ /* now delete properties */ - int k; - NETPROP prop; - key.dptr = (char*)∝ - key.dsize = NETPROP_KEY_SIZE; - prop.obj_id = obj_id; - for (k = (prop_id) ? prop_id : 1; k <= result; k++){ - if (xset[k]){ - prop.id = (uint8)k; - if (delete(key)) { - result = -0xf6; - break; - } - } - } /* for */ - if (result > 0) result=0; + int k; + NETPROP prop; + key.dptr = (char*)∝ + key.dsize = NETPROP_KEY_SIZE; + prop.obj_id = obj_id; + for (k = (prop_id) ? prop_id : 1; k <= result; k++){ + if (xset[k]){ + prop.id = (uint8)k; + if (delete(key)) { + result = -0xf6; + break; + } + } + } /* for */ + if (result > 0) result=0; } else result=-0xff; dbmclose(); } @@ -413,24 +448,31 @@ static int prop_delete_member(uint32 obj_id, int prop_id, int prop_security, val.obj_id = obj_id; val.prop_id = (uint8)prop_id; val.segment = (uint8)0; - data = fetch(key); - while (1) { - val.segment++; - data = fetch(key); + while (val.segment++ < (uint8)255) { + data = fetch(key); if (data.dptr != NULL) { - NETVAL *v = (NETVAL*)data.dptr; - uint8 *p = v->value; - int k = 0; - while (k++ < 32){ - if (GET_BE32(p) == member_id) { - memset(p, 0, 4); - memcpy(&val, v, sizeof(NETVAL)); - data.dptr = (char*)&val; - if (store(key, data)) result=-0xff; - else result=0; - goto L1; - } else p += 4; - } + NETVAL *v = (NETVAL*)data.dptr; + uint8 *p = v->value; + int k = 0; + while (k++ < 32){ + uint32 id=GET_BE32(p); + if (id == member_id) { +#if 0 + memset(p, 0, 4); + memcpy(&val, v, sizeof(NETVAL)); +#else /* new since 0.99.pl7 */ + memcpy(&val, v, p - (uint8*)v); + if (k<32) + memcpy(&val.value[(k-1)*4], p+4, (32-k) * 4); + memset(&val.value[124], 0, 4); +#endif + data.dptr = (char*)&val; + if (store(key, data)) result=-0xff; + else result=0; + goto L1; + } + p += 4; + } } else break; } } else result = -0xff; @@ -459,12 +501,12 @@ static int loc_delete_obj(uint32 objid, int security) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr) { - NETPROP *prop=(NETPROP*)data.dptr; - if (prop->flags & P_FL_SET) { /* is set property */ - objs[anz] = prop->obj_id; - props[anz++] = prop->id; - if (anz == LOC_MAX_OBJS) break; - } + NETPROP *prop=(NETPROP*)data.dptr; + if (prop->flags & P_FL_SET) { /* is set property */ + objs[anz] = prop->obj_id; + props[anz++] = prop->id; + if (anz == LOC_MAX_OBJS) break; + } } } while (anz--) /* now try to delete obj members */ @@ -586,15 +628,15 @@ static int find_prop_id(NETPROP *p, uint32 obj_id, int last_prop_id) if (prop->obj_id == obj_id) { if (!flag) flag = (last_prop_id == prop->id); else { - data = fetch(key); - prop = (NETPROP*)data.dptr; - if (data.dptr != NULL && name_match(prop->name, p->name) - && (b_acc(obj_id, prop->security, 0x00)== 0) ) { - XDPRINTF((2,0, "found PROP %s, id=0x%x", prop->name, (int) prop->id)); - result = 0; - memcpy(p, prop, sizeof(NETPROP)); - break; - } + data = fetch(key); + prop = (NETPROP*)data.dptr; + if (data.dptr != NULL && name_match(prop->name, p->name) + && (b_acc(obj_id, prop->security, 0x00)== 0) ) { + XDPRINTF((2,0, "found PROP %s, id=0x%x", prop->name, (int) prop->id)); + result = 0; + memcpy(p, prop, sizeof(NETPROP)); + break; + } } } } @@ -615,23 +657,23 @@ static int loc_change_prop_security(NETPROP *p, uint32 obj_id) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *prop=(NETPROP*)key.dptr; if (prop->obj_id == obj_id) { - data = fetch(key); - prop = (NETPROP*)data.dptr; - if (data.dptr != NULL && name_match(prop->name, p->name) ) { - uint8 security = p->security; - XDPRINTF((2,0, "found PROP %s, id=0x%x", prop->name, (int) prop->id)); + data = fetch(key); + prop = (NETPROP*)data.dptr; + if (data.dptr != NULL && name_match(prop->name, p->name) ) { + uint8 security = p->security; + XDPRINTF((2,0, "found PROP %s, id=0x%x", prop->name, (int) prop->id)); result = b_acc(obj_id, prop->security, 0x15); if (!result) { - memcpy(p, prop, sizeof(NETPROP)); - p->security = security; - data.dptr = (char*)p; - data.dsize = sizeof(NETPROP); - key.dptr = (char *)p; - key.dsize = NETPROP_KEY_SIZE; - if (store(key, data)) result=-0xff; + memcpy(p, prop, sizeof(NETPROP)); + p->security = security; + data.dptr = (char*)p; + data.dsize = sizeof(NETPROP); + key.dptr = (char *)p; + key.dsize = NETPROP_KEY_SIZE; + if (store(key, data)) result=-0xff; } - break; - } + break; + } } } } else result = -0xff; @@ -639,7 +681,6 @@ static int loc_change_prop_security(NETPROP *p, uint32 obj_id) return(result); } - static int loc_get_prop_val(uint32 obj_id, int prop_id, int prop_security, int segment, uint8 *property_value, uint8 *more_segments) { @@ -686,19 +727,21 @@ static int prop_find_member(uint32 obj_id, int prop_id, int prop_security, key.dptr = (char*)&val; val.obj_id = obj_id; val.prop_id = (uint8)prop_id; - val.segment = (uint8)1; - data = fetch(key); - if (data.dptr != NULL){ - NETVAL *v = (NETVAL*)data.dptr; - uint8 *p=v->value; - int k=0; - XDPRINTF((2,0, "found VAL 0x%x, %d", obj_id, prop_id)); - while (k++ < 32){ - uint32 id = GET_BE32(p); - if (id == member_id) { - result = 0; - break; - } else p += 4; + val.segment = (uint8)0; + while (val.segment++ < (uint8)255) { + data = fetch(key); + if (data.dptr != NULL){ + NETVAL *v = (NETVAL*)data.dptr; + uint8 *p=v->value; + int k=0; + XDPRINTF((2,0, "found VAL 0x%x, %d segment %d", obj_id, prop_id, val.segment)); + while (k++ < 32){ + uint32 id = GET_BE32(p); + if (id == member_id) { + result = 0; + break; + } else p += 4; + } } } } else result = -0xff; @@ -722,31 +765,34 @@ static int prop_add_member(uint32 obj_id, int prop_id, int prop_security, val.prop_id = (uint8)prop_id; val.segment = (uint8)0; while (!result) { - val.segment++; - data = fetch(key); - if (data.dptr != NULL){ - NETVAL *v = (NETVAL*)data.dptr; - uint8 *p = v->value; - int k = 0; - while (k++ < 32){ - uint32 null_id = 0; - if (!memcmp(p, (char*)&null_id, 4)) { - U32_TO_BE32(member_id, p); - memcpy(&val, v, sizeof(NETVAL)); - data.dptr = (char*)&val; - key.dptr = (char*)&val; - if (store(key, data)) result=-0xff; - goto L1; - } else p += 4; - } - } else { - memset(val.value, 0, 128); - U32_TO_BE32(member_id, val.value); - data.dptr = (char*)&val; - data.dsize = sizeof(NETVAL); - if (store(key, data)) result=-0xff; - goto L1; - } + if (val.segment++ < (uint8)255) { + data = fetch(key); + if (data.dptr != NULL){ + NETVAL *v = (NETVAL*)data.dptr; + uint8 *p = v->value; + int k = 0; + while (k++ < 32){ + uint32 null_id = 0; + if (!memcmp(p, (char*)&null_id, 4)) { + U32_TO_BE32(member_id, p); + memcpy(&val, v, sizeof(NETVAL)); + data.dptr = (char*)&val; + key.dptr = (char*)&val; + if (store(key, data)) result=-0xff; + goto L1; + } else p += 4; + } + } else { + memset(val.value, 0, 128); + U32_TO_BE32(member_id, val.value); + data.dptr = (char*)&val; + data.dsize = sizeof(NETVAL); + if (store(key, data)) result=-0xff; + goto L1; + } + } else + /* no more free cells, perhaps we need better result code */ + result=-0xff; } /* while */ } else result = -0xff; L1: @@ -756,7 +802,7 @@ L1: static int ins_prop_val(uint32 obj_id, NETPROP *prop, int segment, - uint8 *property_value, int erase_segments) + uint8 *property_value, int erase_segments) { int result = b_acc(obj_id, prop->security, 0x11); if (result) return(result); @@ -779,11 +825,10 @@ static int ins_prop_val(uint32 obj_id, NETPROP *prop, int segment, data.dsize = sizeof(NETVAL); data.dptr = (char*)&val; if (!store(key, data)) { - result = 0; - if (erase_segments == 0xff){ - val.segment++; - while (!delete(key)) val.segment++; - } + result = 0; + if (erase_segments == 0xff){ + while (val.segment++ < (uint8)255 && !delete(key)); + } } } } else result = -0xff; @@ -793,10 +838,10 @@ static int ins_prop_val(uint32 obj_id, NETPROP *prop, int segment, int nw_get_prop_val_by_obj_id(uint32 obj_id, int segment_nr, - uint8 *prop_name, int prop_namlen, - uint8 *property_value, - uint8 *more_segments, - uint8 *property_flags) + uint8 *prop_name, int prop_namlen, + uint8 *property_value, + uint8 *more_segments, + uint8 *property_flags) { NETPROP prop; int result=-0xff; @@ -806,7 +851,7 @@ int nw_get_prop_val_by_obj_id(uint32 obj_id, if ((result=find_first_prop_id(&prop, obj_id))==0){ if ((result=loc_get_prop_val(obj_id, prop.id, prop.security, segment_nr, - property_value, more_segments)) == 0){ + property_value, more_segments)) == 0){ *property_flags = prop.flags; } } @@ -814,12 +859,12 @@ int nw_get_prop_val_by_obj_id(uint32 obj_id, } int nw_get_prop_val(int object_type, - uint8 *object_name, int object_namlen, - int segment_nr, - uint8 *prop_name, int prop_namlen, - uint8 *property_value, - uint8 *more_segments, - uint8 *property_flags) + uint8 *object_name, int object_namlen, + int segment_nr, + uint8 *prop_name, int prop_namlen, + uint8 *property_value, + uint8 *more_segments, + uint8 *property_flags) { NETOBJ obj; int result=-0xff; @@ -828,17 +873,17 @@ int nw_get_prop_val(int object_type, if ((result = find_obj_id(&obj)) == 0){ result = nw_get_prop_val_by_obj_id(obj.id, segment_nr, - prop_name, prop_namlen, - property_value, - more_segments, - property_flags); + prop_name, prop_namlen, + property_value, + more_segments, + property_flags); } return(result); } int nw_delete_property(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen) { NETOBJ obj; uint8 prop_name_x[20]; @@ -866,10 +911,10 @@ int nw_is_member_in_set(uint32 obj_id, char *propname, uint32 member_id) } int nw_is_obj_in_set(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen, - int member_type, - uint8 *member_name, int member_namlen) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + int member_type, + uint8 *member_name, int member_namlen) { NETOBJ obj; NETOBJ mobj; @@ -893,10 +938,10 @@ int nw_is_obj_in_set(int object_type, } int nw_add_obj_to_set(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen, - int member_type, - uint8 *member_name, int member_namlen) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + int member_type, + uint8 *member_name, int member_namlen) { NETOBJ obj; NETOBJ mobj; @@ -924,10 +969,10 @@ int nw_add_obj_to_set(int object_type, } int nw_delete_obj_from_set(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen, - int member_type, - uint8 *member_name, int member_namlen) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + int member_type, + uint8 *member_name, int member_namlen) { NETOBJ obj; NETOBJ mobj; @@ -952,10 +997,10 @@ int nw_delete_obj_from_set(int object_type, int nw_write_prop_value(int object_type, - uint8 *object_name, int object_namlen, - int segment_nr, int erase_segments, - uint8 *prop_name, int prop_namlen, - uint8 *property_value) + uint8 *object_name, int object_namlen, + int segment_nr, int erase_segments, + uint8 *prop_name, int prop_namlen, + uint8 *property_value) { NETOBJ obj; NETPROP prop; @@ -969,7 +1014,7 @@ int nw_write_prop_value(int object_type, if ((result = find_obj_id(&obj)) == 0){ if ((result=find_first_prop_id(&prop, obj.id))==0){ result=ins_prop_val(obj.id, &prop, segment_nr, - property_value, erase_segments); + property_value, erase_segments); } } @@ -978,9 +1023,9 @@ int nw_write_prop_value(int object_type, int nw_change_prop_security(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen, - int prop_security) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + int prop_security) { NETOBJ obj; NETPROP prop; @@ -998,11 +1043,11 @@ int nw_change_prop_security(int object_type, int nw_scan_property(NETPROP *prop, int object_type, - uint8 *object_name, - int object_namlen, - uint8 *prop_name, - int prop_namlen, - uint32 *last_scan) + uint8 *object_name, + int object_namlen, + uint8 *prop_name, + int prop_namlen, + uint32 *last_scan) { NETOBJ obj; int result; @@ -1019,7 +1064,7 @@ int nw_scan_property(NETPROP *prop, if ((result=find_prop_id(prop, obj.id, last_prop_id))==0){ *last_scan = prop->id; if (!loc_get_prop_val(obj.id, prop->id, prop->security, 1, - NULL, NULL)) + NULL, NULL)) result = 0xff; /* Has prop Values */ } } @@ -1061,12 +1106,12 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr){ - NETOBJ *o=(NETOBJ*)data.dptr; - if (o->type == obj->type && !strcmp(o->name, obj->name)){ - obj->id = o->id; /* fill ID */ - result = -0xee; /* already exist */ - break; - } + NETOBJ *o=(NETOBJ*)data.dptr; + if (o->type == obj->type && !strcmp(o->name, obj->name)){ + obj->id = o->id; /* fill ID */ + result = -0xee; /* already exist */ + break; + } } } if (!result){ @@ -1075,9 +1120,9 @@ int nw_create_obj(NETOBJ *obj, uint32 wanted_id) key.dsize = NETOBJ_KEY_SIZE; key.dptr = (char*)obj; while(1) { - obj->id++; - data = fetch(key); - if (data.dptr == NULL) break; + obj->id++; + data = fetch(key); + if (data.dptr == NULL) break; } data.dsize = sizeof(NETOBJ); data.dptr = (char*)obj; @@ -1097,8 +1142,8 @@ int nw_obj_has_prop(NETOBJ *obj) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *p=(NETPROP*)key.dptr; if (p->obj_id == obj->id) { - result = 1; - break; + result = 1; + break; } } } @@ -1115,13 +1160,13 @@ static int nw_create_obj_prop(uint32 obj_id, NETPROP *prop) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { NETPROP *p=(NETPROP*)key.dptr; if (p->obj_id == obj_id) { - data = fetch(key); - p = (NETPROP*)data.dptr; - if (data.dptr != NULL && !strcmp(prop->name, p->name)){ - prop->id = p->id; - prop->obj_id = obj_id; - result = -0xed; /* Property exists */ - if (p->security != prop->security || + data = fetch(key); + p = (NETPROP*)data.dptr; + if (data.dptr != NULL && !strcmp(prop->name, p->name)){ + prop->id = p->id; + prop->obj_id = obj_id; + result = -0xed; /* Property exists */ + if (p->security != prop->security || p->flags != prop->flags) { /* added 16-Aug-97 0.99.pl1 */ XDPRINTF((1, 0, "prop '%s' got new security/flag=0x%x / %d", @@ -1133,15 +1178,15 @@ static int nw_create_obj_prop(uint32 obj_id, NETPROP *prop) data.dsize = sizeof(NETPROP); data.dptr = (char *)p; if (store(key, data)) result = -0xff; - } - break; - } else founds[p->id]++; + } + break; + } else founds[p->id]++; } } if (!result){ int k = 0; while (++k < sizeof(founds) ) { - if (!founds[k]) break; /* free slot */ + if (!founds[k]) break; /* free slot */ } key.dsize = NETPROP_KEY_SIZE; key.dptr = (char *)prop; @@ -1159,9 +1204,9 @@ static int nw_create_obj_prop(uint32 obj_id, NETPROP *prop) } int nw_create_prop(int object_type, - uint8 *object_name, int object_namlen, - uint8 *prop_name, int prop_namlen, - int prop_flags, int prop_security) + uint8 *object_name, int object_namlen, + uint8 *prop_name, int prop_namlen, + int prop_flags, int prop_security) /* creats property for an object */ { NETOBJ obj; @@ -1183,7 +1228,7 @@ int nw_create_prop(int object_type, static int nw_new_obj(uint32 *wanted_id, char *objname, int objtype, - int objflags, int objsecurity) + int objflags, int objsecurity) { NETOBJ obj; int result; @@ -1199,8 +1244,8 @@ static int nw_new_obj(uint32 *wanted_id, 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) + char *propname, int propflags, int propsecurity, + char *value, int valuesize, int ever) /* * creats new property value, if needed creats Object * and the property, @@ -1234,8 +1279,12 @@ uint32 nw_new_obj_prop(uint32 wanted_id, /* some property names */ /*STANDARD NOVELL properties */ -static uint8 *pn_password=(uint8*) "PASSWORD"; -static uint8 *pn_login_control=(uint8*)"LOGIN_CONTROL"; +static uint8 *pn_password=(uint8*) "PASSWORD"; +static uint8 *pn_login_control=(uint8*) "LOGIN_CONTROL"; +static uint8 *pn_security_equals=(uint8*) "SECURITY_EQUALS"; +static uint8 *pn_groups_i_m_in=(uint8*) "GROUPS_I'M_IN"; +static uint8 *pn_group_members=(uint8*) "GROUP_MEMBERS"; + /* OWN properties */ static uint8 *pn_unix_user=(uint8*) "UNIX_USER"; @@ -1283,6 +1332,36 @@ static MYPASSWD *nw_getpwnam(uint32 obj_id) return(NULL); } +int nw_is_security_equal(uint32 id1, uint32 id2) +/* returns 0 if id2 has same security as id1 */ +{ + return(nw_is_member_in_set(id2, pn_security_equals, id1)); +} + +int get_groups_i_m_in(uint32 id, uint32 *gids) +/* returns max. 32 groups */ +{ + uint8 buff[128]; + uint8 more_segments=0; + uint8 property_flags; + int result=nw_get_prop_val_by_obj_id(id, 1, + pn_groups_i_m_in, strlen(pn_groups_i_m_in), + buff, &more_segments, &property_flags); + if (!result) { + uint8 *p=buff; + int k=-1; + while (++k < 32) { + *gids=GET_BE32(p); + p+=4; + if (*gids) { + gids++; + result++; + } + } + } else result=0; + return(result); +} + int get_guid(int *gid, int *uid, uint32 obj_id, uint8 *name) /* searched for gid und uid of actual obj */ { @@ -1300,25 +1379,6 @@ int get_guid(int *gid, int *uid, uint32 obj_id, uint8 *name) } } -int get_home_dir(uint8 *homedir, uint32 obj_id) -/* searches for UNIX homedir of actual obj */ -{ - MYPASSWD *pw = nw_getpwnam(obj_id); - if (NULL != pw) { - int len=strlen(pw->pw_dir); - if (!len) { - *homedir++ = '/'; - *homedir = '\0'; - len =1; - } else - strmaxcpy(homedir, pw->pw_dir, min(255, len)); - return(len); - } else { - *homedir='\0'; - return(0); - } -} - static int crypt_pw_ok(uint8 *password, char *passwd) /* returns 0 if not ok */ { @@ -1354,7 +1414,8 @@ int nw_test_passwd(uint32 obj_id, uint8 *vgl_key, uint8 *akt_key) obj_id, vgl_key, akt_key); if (result < 1) return(result); - if (obj_id == 1) return(-0xff); /* SUPERVISOR */ + if (obj_id == 1) return(-0xff); + /* the real SUPERVISOR must use netware passwords */ if (password_scheme & PW_SCHEME_LOGIN) { if (!(password_scheme & PW_SCHEME_ALLOW_EMPTY_PW)) { @@ -1394,19 +1455,165 @@ int nw_test_unenpasswd(uint32 obj_id, uint8 *password) } else return(-0xff); } +/* added Routines from Paolo Prandini: mst:25-Apr-00 */ +static int nw_update_oldpasswd(uint32 obj_id, char *pwd) +{ + char *pn_control="OLD_PASSWORDS"; + uint8 more_segments; + uint8 property_flags; + int segment = 1; + int result; + uint8 segm[128]; + // Read OLD_PASSWORDS bindery object + result=nw_get_prop_val_by_obj_id(obj_id, segment, + pn_control, strlen(pn_control), + segm, &more_segments, &property_flags); + if (result < 0) { + // Here if OLD_PASSWORDS object not found + return 0; + } + // Check if password already present in data object + for (segment=0;segment<8;segment++) { + if (memcmp(pwd,segm+segment*16,16)==0)return 1; + } + // Update record + memcpy(segm+16,segm,128-16); + memcpy(segm,pwd,16); + + nw_new_obj_prop(obj_id, NULL, 0, 0, 0, + pn_control, P_FL_STAT|P_FL_ITEM, 0x32, + segm, 128, 1); + return(0); +} + +int nw_set_login_control(uint32 obj_id, LOGIN_CONTROL *plc) +{ + char *pn_login_control="LOGIN_CONTROL"; + nw_new_obj_prop(obj_id, NULL, 0, 0, 0, + pn_login_control, P_FL_STAT|P_FL_ITEM, 0x32, + (uint8 *)plc, sizeof(LOGIN_CONTROL), 1); + return(0); +} + +int nw_get_login_control(uint32 obj_id, LOGIN_CONTROL *plc) +{ + uint8 more_segments; + uint8 property_flags; + int segment = 1; + char *pn_login_control="LOGIN_CONTROL"; + int result; + uint8 segm[128]; + + // Read LOGIN_CONTROL bindery object + result=nw_get_prop_val_by_obj_id(obj_id, segment, + pn_login_control, strlen(pn_login_control), + segm, &more_segments, &property_flags); + + if (result < 0) { + // Here if LOGIN_CONTROL object not found + char *pn_user_defaults="USER_DEFAULTS"; + USER_DEFAULTS ud; + XDPRINTF((5, 0, "Reading USER_DEFAULTS for user %x",obj_id)); + // Try reading USER_DEFAULTS object + segment=1; + result=nw_get_prop_val_by_obj_id(1, segment, + pn_user_defaults, strlen(pn_user_defaults), + segm, &more_segments, &property_flags); + if (result < 0) return -1; + XDPRINTF((5, 0, "Read USER_DEFAULTS")); + memcpy(&ud,segm,sizeof(ud)); + // Ok, now fill LOGIN_CONTROL with data from USER_DEFAULTS; + memset(plc,0,sizeof(LOGIN_CONTROL)); + plc->accountExpiresYear = ud.accountExpiresYear; + plc->accountExpiresMonth = ud.accountExpiresMonth; + plc->accountExpiresDay = ud.accountExpiresDay; + plc->restrictionFlags = ud.restrictionFlags; + memcpy(plc->expirationInterval, ud.expirationInterval, + sizeof(plc->expirationInterval)); + plc->graceReset = ud.graceReset; + plc->minimumPasswordLength = ud.minimumPasswordLength; + memcpy(plc->maxConcurrentConnections, ud.maxConcurrentConnections, + sizeof(plc->maxConcurrentConnections)); + memcpy(plc->timeBitMap, ud.timeBitMap, sizeof(ud.timeBitMap)); + memcpy(plc->maxDiskBlocks, ud.maxDiskBlocks, sizeof(plc->maxDiskBlocks)); + } else + memcpy(plc,segm,sizeof(LOGIN_CONTROL)); + + return 0; +} + +// Check if the new crypted password is acceptable or not +static int nw_valid_keynewpasswd(uint32 obj_id, int pwdlen, char *newpasswd) +{ + LOGIN_CONTROL lc; + int result; + + XDPRINTF((5, 0, "Change password for user %x with crypted pwd",obj_id)); + + result = nw_get_login_control(obj_id, &lc); + if (result < 0) return(0); /* No restrictions available */ + + XDPRINTF((2, 0, "CHPWD:len(pwd)=%d limit=%d", pwdlen, lc.minimumPasswordLength)); + + if (pwdlen < lc.minimumPasswordLength) + return (-0xd8); // PASSWORD TOO SHORT + return 0; +} static int nw_set_enpasswd(uint32 obj_id, uint8 *passwd, int dont_ch) { uint8 *prop_name=pn_password; + LOGIN_CONTROL lc; + int result; + if (passwd && *passwd) { - if ((!dont_ch) || (nw_get_prop_val_str(obj_id, prop_name, NULL) < 1)) - nw_new_obj_prop(obj_id, NULL, 0, 0, 0, - prop_name, P_FL_STAT|P_FL_ITEM, 0x44, - passwd, 16, 1); + if ((!dont_ch) || (nw_get_prop_val_str(obj_id, prop_name, NULL) < 1)) { + result=nw_update_oldpasswd(obj_id,passwd); + if (nw_get_login_control(obj_id,&lc)==0) { + if (lc.restrictionFlags&2) { + if (result) return -0xd7; + } + } + nw_new_obj_prop(obj_id, NULL, 0, 0, 0, + prop_name, P_FL_STAT|P_FL_ITEM, 0x44, + passwd, 16, 1); + } } else if (!dont_ch) (void)loc_delete_property(obj_id, prop_name, 0, 1); + + // Here we must update LOGIN_CONTROL properties + if (nw_get_login_control(obj_id,&lc)==0) { + struct tm exptm,*tm; + time_t t,expiry; + + 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 */ + if (lc.passwordGraceLogins!=255) + lc.passwordGraceLogins=lc.graceReset; + + // Now renew expiration date + time(&t); + t += ( GET_BE16(lc.expirationInterval) *24L*3600L ); + tm = localtime(&t); + + lc.passwordExpiresYear = tm->tm_year; + lc.passwordExpiresMonth = tm->tm_mon+1; + lc.passwordExpiresDay = tm->tm_mday; + + nw_set_login_control(obj_id,&lc); + } + } return(0); } @@ -1428,7 +1635,7 @@ int nw_set_passwd(uint32 obj_id, char *password, int dont_ch) * from ncp request */ int nw_keychange_passwd(uint32 obj_id, uint8 *cryptkey, uint8 *oldpass, - int cryptedlen, uint8 *newpass, uint32 act_id) + int cryptedlen, uint8 *newpass, int id_flags) /* returns 1 if new password is zero */ { uint8 storedpass[200]; @@ -1451,7 +1658,7 @@ int nw_keychange_passwd(uint32 obj_id, uint8 *cryptkey, uint8 *oldpass, XDPRINTF((5, 0, "ncp old: %s", hex_str(buf, oldpass, 8))); if (result < 0) { /* wrong passwd */ - if (1 == act_id) { /* supervisor is changing passwd */ + if (id_flags&1) { /* supervisor (equivalence) is changing passwd */ U32_TO_BE32(obj_id, s_uid); shuffle(s_uid, buf, 0, storedpass); nw_encrypt(cryptkey, storedpass, keybuff); @@ -1463,119 +1670,21 @@ int nw_keychange_passwd(uint32 obj_id, uint8 *cryptkey, uint8 *oldpass, return(-0xff); /* if not BLANK then error */ } else return(-0xff); } + result=nw_valid_keynewpasswd(obj_id, len, storedpass); + if (result<0) return result; + XDPRINTF((5, 0, "ncp new: %s", hex_str(buf,newpass, 16))); nw_decrypt_newpass(storedpass, newpass, newpass); nw_decrypt_newpass(storedpass+8, newpass+8, newpass+8); XDPRINTF((5, 0, "realnew: %s", hex_str(buf,newpass, 16))); - nw_set_enpasswd(obj_id, newpass, 0); + result=nw_set_enpasswd(obj_id, newpass, 0); + if (result<0) return result; /* testing for zero password */ U32_TO_BE32(obj_id, s_uid); shuffle(s_uid, buf, 0, storedpass); return(memcmp(newpass, storedpass, 16) ? 0 : 1); } -static int nw_test_time_access(uint32 obj_id) -/* - * Routine from Matt Paley - * and code from Mark Robson -*/ -{ - time_t t,expiry; - struct tm exptm; - struct tm *tm; - uint8 more_segments; - uint8 property_flags; - uint8 buff[200]; - int segment = 1; - int half_hours; - int result=nw_get_prop_val_by_obj_id(obj_id, segment, - pn_login_control, strlen(pn_login_control), - buff, &more_segments, &property_flags); - if (result < 0) - return(0); /* No time limits available */ - - /* Check if account disabled - MR */ - - if (buff[3] != 0) /* 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 (buff[0] != 0) - { - exptm.tm_year = buff[0]; - exptm.tm_mon = buff[1]-1; - exptm.tm_mday = buff[2]; - 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); - if ((buff[14+(half_hours/8)] & (1<<(half_hours % 8))) != 0) - return(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 */ -} - -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 result=nw_get_prop_val_by_obj_id(obj_id, segment, - propname, strlen(propname), - buff, &more_segments, &property_flags); - if (result < 0) - return(0); /* we have no limits */ - else { - uint8 *p=buff; - int k=0; - while (k++ < 12) { - if ( (IPXCMPNET(client_adr->net, p)) - && ( (IPXCMPNODE(client_adr->node, p+4) ) - || (IPXCMPNODE(wildnode, p+4))) ) - return(0); - p+=10; - } - } - XDPRINTF((1, 0, "No access for user %x at Station %s", - obj_id, visable_ipx_adr(client_adr))); - return(-0xdb); /* unauthorized login station */ -} - -int nw_test_adr_time_access(uint32 obj_id, ipxAddr_t *client_adr) -{ - int result; - if (obj_id==1 && (entry8_flags & 8)) - return(0); /* no limits for SU */ - result=nw_test_adr_access(obj_id, client_adr); - if (!result) - result=nw_test_time_access(obj_id); - return(result); -} - - static int nw_new_add_prop_member(uint32 obj_id, char *propname, int propflags, int propsecurity, uint32 member_id) @@ -1587,7 +1696,7 @@ static int nw_new_add_prop_member(uint32 obj_id, char *propname, prop.flags = (uint8) (propflags | P_FL_SET); /* always SET */ prop.security = (uint8) propsecurity; result = nw_create_obj_prop(obj_id, &prop); - + if (!result || result == -0xed) { /* created or exists */ if (-0xea == (result=prop_find_member(obj_id, prop.id, prop.security, member_id))) return(prop_add_member(obj_id, prop.id, prop.security, member_id)); @@ -1597,6 +1706,7 @@ static int nw_new_add_prop_member(uint32 obj_id, char *propname, return(result); } + int nwdbm_mkdir(char *unixname, int mode, int flags) /* flags & 1 = set x permiss flag in upper dirs */ { @@ -1620,7 +1730,7 @@ int nwdbm_mkdir(char *unixname, int mode, int flags) } int nwdbm_rmdir(char *path) -/* removes full directory */ +/* removes full directory, without subdirs */ { DIR *f=opendir(path); if (f) { @@ -1645,7 +1755,7 @@ int nwdbm_rmdir(char *path) static void create_nw_db(char *fn, int always) { - char fname[200]; + char fname[300]; struct stat stbuff; (void)get_div_pathes(fname, fn, 1, ".dir"); if (stat(fname, &stbuff)){ @@ -1654,7 +1764,21 @@ static void create_nw_db(char *fn, int always) (void)get_div_pathes(fname, fn, 1, ".dir"); } if (always || stat(fname, &stbuff)){ - int fd = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); + int fd; + if (always) { /* we save old dbm */ + char pa[300]; + char fna[300]; + (void)get_div_pathes(pa, "nwdbm.sav", 1, NULL); + nwdbm_mkdir(pa, 0700, 0); + sprintf(fna, "%s/%s.dir", pa, fn); + unlink(fna); + rename(fname, fna); + sprintf(fna, "%s/%s.pag", pa, fn); + unlink(fna); + (void)get_div_pathes(pa, fn, 1, ".pag"); + rename(pa, fna); + } + fd = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); if (fd > -1) close(fd); } chmod(fname, 0600); @@ -1680,55 +1804,65 @@ static void add_pr_queue(uint32 q_id, } XDPRINTF((2,0, "ADD Q=%s, V=%s, C=%s", q_name, q_directory, q_command)); nw_new_obj_prop(q_id, NULL, 0, 0, 0, - "Q_DIRECTORY", P_FL_ITEM, 0x31, - q_directory, strlen(q_directory), 1); + "Q_DIRECTORY", P_FL_ITEM, 0x31, + q_directory, strlen(q_directory), 1); /* this is mars_nwe own property to handle the print job direct !!! */ if (q_command && *q_command) { nw_new_obj_prop(q_id ,NULL, 0 , 0 , 0 , - "Q_UNIX_PRINT", P_FL_ITEM| P_FL_DYNA, 0x31, - q_command, strlen(q_command), 1); + "Q_UNIX_PRINT", P_FL_ITEM| P_FL_DYNA, 0x31, + q_command, strlen(q_command), 1); } nw_new_add_prop_member(q_id, "Q_USERS", P_FL_STAT, 0x31, ge_id); nw_new_add_prop_member(q_id, "Q_OPERATORS", P_FL_STAT, 0x31, su_id); nw_new_obj_prop(q_id , NULL, 0 , 0 , 0 , - "Q_SERVERS", P_FL_SET, 0x31, - NULL, 0, 0); + "Q_SERVERS", P_FL_SET, 0x31, + NULL, 0, 0); } static void add_pr_server(uint32 ps_id, char *ps_name, char *ps_queue, - uint32 su_id, uint32 ge_id) + uint32 su_id, uint32 ge_id, int is_user) { - XDPRINTF((2,0, "ADD PS=%s, Q=%s", ps_name, ps_queue)); - nw_new_obj(&ps_id, ps_name, 0x7, O_FL_STAT, 0x31); - nw_new_add_prop_member(ps_id, "PS_OPERATORS", P_FL_STAT, 0x31, su_id); - nw_new_add_prop_member(ps_id, "PS_USERS", P_FL_STAT, 0x31, ge_id); - + XDPRINTF((1,0, "ADD PS%s=%s, Q=%s", is_user?"(User)":"", ps_name, ps_queue)); + if (!is_user) { + nw_new_obj(&ps_id, ps_name, 0x7, O_FL_STAT, 0x31); + nw_new_add_prop_member(ps_id, "PS_OPERATORS", P_FL_STAT, 0x31, su_id); + nw_new_add_prop_member(ps_id, "PS_USERS", P_FL_STAT, 0x31, ge_id); + } else { + NETOBJ obj; + strmaxcpy((char*)obj.name, (char*)ps_name, 47); + obj.type = 0x1; /* USER */ + if (find_obj_id(&obj)) { + XDPRINTF((1, 0, "add_pr_server:user=%s not exist", obj.name)); + return; + } + ps_id=obj.id; + } if (ps_queue && *ps_queue) { NETOBJ obj; strmaxcpy((char*)obj.name, (char*)ps_queue, 47); obj.type = 0x3; /* QUEUE */ - if (!find_obj_id(&obj)) + if (!find_obj_id(&obj)) { nw_new_add_prop_member(obj.id, "Q_SERVERS", P_FL_STAT, 0x31, ps_id); + } } - } static void add_user_to_group(uint32 u_id, uint32 g_id) { - nw_new_add_prop_member(u_id, "GROUPS_I'M_IN", P_FL_STAT, 0x31, g_id); - nw_new_add_prop_member(u_id, "SECURITY_EQUALS", P_FL_STAT, 0x32, g_id); - nw_new_add_prop_member(g_id, "GROUP_MEMBERS", P_FL_STAT, 0x31, u_id); + nw_new_add_prop_member(u_id, pn_groups_i_m_in, P_FL_STAT, 0x31, g_id); + nw_new_add_prop_member(u_id, pn_security_equals, P_FL_STAT, 0x32, g_id); + nw_new_add_prop_member(g_id, pn_group_members, P_FL_STAT, 0x31, u_id); } static void add_user_2_unx(uint32 u_id, char *unname) { if (unname && *unname) nw_new_obj_prop(u_id, NULL, 0 , 0 , 0 , - pn_unix_user, P_FL_ITEM, 0x30, - (char*)unname, strlen(unname), 1); + pn_unix_user, P_FL_ITEM, 0x30, + (char*)unname, strlen(unname), 1); } extern int test_allow_password_change(uint32 id) @@ -1742,7 +1876,7 @@ extern int test_allow_password_change(uint32 id) buff, &more_segments, &property_flags); if (result > -1 && (GET_BE32(buff) & 1)) return(-0xff); - + /* hint from (Mr. Charlie Root) */ result=nw_get_prop_val_by_obj_id(id, segment, pn_login_control, strlen(pn_login_control), @@ -1751,7 +1885,7 @@ extern int test_allow_password_change(uint32 id) /* can user change password ? */ if (result > -1 && (buff[62] & 1) ) /* Restriction Mask */ return(-0xff); - + return(0); } @@ -1762,8 +1896,8 @@ static void add_remove_special_flags(uint32 obj_id, int flags) uint8 buff[4]; U32_TO_BE32(flags, buff); nw_new_obj_prop(obj_id, NULL, 0, 0, 0, - pn_special_flags, P_FL_STAT|P_FL_ITEM, 0x33, - buff, sizeof(buff), 1); + pn_special_flags, P_FL_STAT|P_FL_ITEM, 0x33, + buff, sizeof(buff), 1); } else (void)loc_delete_property(obj_id, pn_special_flags, 0, 1); } @@ -1774,18 +1908,25 @@ static void add_user_g(uint32 u_id, uint32 g_id, int flags, int set_flags) { /* Typ Flags Security */ +#if 0 /* perhaps Compiler BUG ? problem since gcc 2.7.2.3, 29-Jan-99 */ dont_ch = (nw_new_obj(&u_id, name, 0x1 , 0x0, 0x31) && dont_ch); - +#else + if (!nw_new_obj(&u_id, name, 0x1 , 0x0, 0x31)) + dont_ch = 0; +#endif if (dont_ch) return; XDPRINTF((1, 0, "Add/Change User='%s', UnixUser='%s'", - name, unname)); + name, unname)); add_user_to_group(u_id, g_id); add_user_2_unx(u_id, unname); if (password && *password) { - if (*password == '-') *password='\0'; + // if (*password == '-') *password='\0'; + // if (password[0] == '-' && password[1] != '\0') + if (password[0] == '-' && password[1] == '\0') /* mst: 25-Apr-00 */ + *password='\0'; nw_set_passwd(u_id, password, dont_ch); } if (set_flags) @@ -1799,8 +1940,8 @@ static void add_group(char *name, char *unname, char *password) (void) nw_new_obj(&g_id, name, 0x2 , 0x0, 0x31); if (unname && *unname) nw_new_obj_prop(g_id, NULL, 0 , 0 , 0 , - "UNIX_GROUP", P_FL_ITEM, 0x33, - (char*)unname, strlen(unname), 1); + "UNIX_GROUP", P_FL_ITEM, 0x33, + (char*)unname, strlen(unname), 1); } @@ -1820,8 +1961,9 @@ static int get_sys_unixname(uint8 *unixname, uint8 *sysname, uint8 *sysentry) uint8 *p; for (p=optionstr; *p; p++) { if (*p=='k') { - result=1; - break; + result|=1; /* downshift */ + } else if (*p=='t') { + result|=2; /* trustees */ } } /* for */ } /* if */ @@ -1830,7 +1972,7 @@ static int get_sys_unixname(uint8 *unixname, uint8 *sysname, uint8 *sysentry) *(pp+1) = '\0'; if (stat(unixname, &statb) < 0) - nwdbm_mkdir(unixname, 0777, 1); + nwdbm_mkdir(unixname, 0751, 1); if (stat(unixname, &statb) < 0 || !S_ISDIR(statb.st_mode)) { errorp(1, "No good SYS", "unix name='%s'", unixname); @@ -1896,6 +2038,7 @@ static void correct_user_dirs(uint32 objid, uint8 *objname, int uid, int gid) uint8 *pp; uint8 *p1; int l; + int mask; DIR *f; memcpy(fndir, sys_unixname, sys_unixnamlen); /* SYS/MAIL */ @@ -1909,18 +2052,50 @@ static void correct_user_dirs(uint32 objid, uint8 *objname, int uid, int gid) upstr(p); upstr(buf1); } - (void)mkdir(fndir, 0733); - (void)chmod(fndir, 0733); + + if (sys_has_trustee) + mask = 0700; /* other rights may be given via trustees */ + else + mask = 0733; /* everybody should be able to write */ + + (void)mkdir(fndir, mask); + (void)chmod(fndir, mask); (void)chown(fndir, uid, gid); + if ((f=opendir(fndir)) != (DIR*)NULL) { struct dirent* dirbuff; *pp='/'; + if (entry17_flags&0x1) { /* creat empty login script */ + struct stat statb; + strcpy(pp+1, "login"); + if (!sys_downshift) + upstr(pp+1); + if (stat(fndir, &statb)) { /* no one exist */ + FILE *f=fopen(fndir, "w"); + if (f) { + fprintf(f, "REM auto created by mars_nwe\r\n"); + fclose(f); + (void)chown(fndir, uid, gid); + chmod(fndir, 0600); + } + } + } + while ((dirbuff = readdir(f)) != (struct dirent*)NULL){ if (dirbuff->d_ino) { + struct stat lstatb; uint8 *name=(uint8*)(dirbuff->d_name); if (name[0] != '.' && name[1] != '.' && name[1] != '\0') { strcpy(pp+1, name); - (void)chown(fndir, uid, gid); + if ( !lstat(fndir, &lstatb) + && !S_ISLNK(lstatb.st_mode) && + lstatb.st_uid != 0 && lstatb.st_gid != 0 + && lstatb.st_uid != uid) { + (void)chown(fndir, uid, gid); + if (sys_has_trustee) { + chmod(fndir, S_ISDIR(lstatb.st_mode) ? 700 : 600); + } + } } } } @@ -1932,6 +2107,7 @@ static void correct_user_dirs(uint32 objid, uint8 *objname, int uid, int gid) upstr(p1); else downstr(p1+5); + unlink(fndir); symlink(buf1, fndir); } @@ -1957,25 +2133,269 @@ void test_ins_unx_user(uint32 id) } } +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 void check_compress_bindery() +/* try to repair and compress bindery, added in 0.99.pl7 */ +{ + char *errstr = "check_compress_bindery"; + int propok = 0; + uint32 objs[LOC_MAX_OBJS]; + int ocount = 0; + + /* for deleting props */ + uint32 d_prop_oid[LOC_MAX_OBJS]; + uint8 d_props[LOC_MAX_OBJS]; + int d_pcount = 0; + + uint32 *prop_oid = NULL; + uint8 *props = NULL; + uint8 *props_fl = NULL; + int pcount = 0; + long tstart = time(NULL); + + sync_dbm(); + XDPRINTF((1,0, "%s starts...", errstr)); + + if (!dbminit(FNOBJ)){ + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETOBJ *obj=(NETOBJ*)data.dptr; + if (ocount == LOC_MAX_OBJS) { + errorp(10, errstr, "to many objs = %d.", ocount); + dbmclose(); + return; + } + objs[ocount++] = obj->id; + } + } + qsort(objs, (size_t)ocount, (size_t)sizeof(uint32), cmp_uint32); + XDPRINTF((1,0, "%s after qsort", errstr)); + + /* we test whether qsort/bsearch will work fine */ + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETOBJ *obj=(NETOBJ*)data.dptr; + if (NULL == bsearch(&obj->id, objs, + (size_t)ocount, (size_t)sizeof(uint32), cmp_uint32)) { + errorp(10, errstr, "bsearch failed at id 0x%lx.", + (unsigned long)obj->id); + dbmclose(); + return; + } + } + } + dbmclose(); + + /* handle all properties */ + if (!dbminit(FNPROP)){ + propok++; +#define LOC_MAX_OBJS_PROPS (LOC_MAX_OBJS * 20) + prop_oid = (uint32*) xmalloc(LOC_MAX_OBJS_PROPS * sizeof(uint32)); + props = (uint8*) xmalloc(LOC_MAX_OBJS_PROPS * sizeof(uint8)); + props_fl = (uint8*) xmalloc(LOC_MAX_OBJS_PROPS * sizeof(uint8)); + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETPROP *prop=(NETPROP*)data.dptr; + if (NULL == bsearch(&prop->obj_id, objs, + (size_t)ocount, (size_t)sizeof(uint32), cmp_uint32)) { + XDPRINTF((1,0, "will delete property %s for obj_id 0x%lx", + prop->name, prop->obj_id)); + if (d_pcount == LOC_MAX_OBJS) break; + d_prop_oid[d_pcount] = prop->obj_id; + d_props[d_pcount++] = prop->id; + } else { + if (pcount == LOC_MAX_OBJS_PROPS) { + errorp(10, errstr, "to many props = %d.", pcount); + propok=0; + break; + } + prop_oid[pcount] = prop->obj_id; + props[pcount] = prop->id; + props_fl[pcount++] = prop->flags; + } + } + } /* for */ + } + dbmclose(); + /* now delete properties which aere not assigned to an object */ + while (d_pcount--) + loc_delete_property(d_prop_oid[d_pcount], (char*)NULL, + d_props[d_pcount], 1); + + XDPRINTF((1,0, "%s after deleting props, propok=%d", errstr, propok)); + + if (propok) { /* correct/compress propertie values */ + int fd=-1; + char tmpfn[300]; + strcpy(tmpfn,"/tmp/nwvalXXXXXX"); +#if 0 + if (mktemp(tmpfn)) { + unlink(tmpfn); + fd=creat(tmpfn, 0600); + } +#else /* mst: 04-Apr-00, patch from (Jukka Ukkonen) */ + fd = mkstemp (tmpfn); +#endif + if (fd > -1) { + if (!dbminit(FNVAL)){ + int i = -1; + NETVAL val; + key.dsize = NETVAL_KEY_SIZE; + key.dptr = (char*)&val; + while (propok && ++i < pcount) { + int is_set = (props_fl[i] & P_FL_SET) ? 1:0; + NETVAL valexp; + int eitems = 0; + uint8 *ep = valexp.value; + val.obj_id = prop_oid[i]; + val.prop_id = props[i]; + val.segment = (uint8)0; + if (is_set) { + memset(&valexp, 0, sizeof(NETVAL)); + valexp.obj_id = val.obj_id; + valexp.prop_id = val.prop_id; + valexp.segment = 1; + d_pcount = 0; + } + while (val.segment++ < (uint8)255) { + data = fetch(key); + if (data.dptr != NULL){ + NETVAL *v = (NETVAL*)data.dptr; + uint8 *p = v->value; + if (is_set) { + int k=0; + while (k++ < 32){ + uint32 id = GET_BE32(p); + if (id) { + if (NULL != bsearch(&id, objs, + (size_t)ocount, (size_t)sizeof(uint32), cmp_uint32)) { + int l=-1; + while (++l < d_pcount) { + if (d_prop_oid[l] == id) { + id=(uint32)0; + break; + } + } + } else id=(uint32)0; + } + if (id) { + d_prop_oid[d_pcount++] = id; + if (eitems > 31) { + if (sizeof(NETVAL) != write(fd, &valexp, sizeof(NETVAL))){ + errorp(1, errstr, "writeerror on %s", tmpfn); + propok=0; + break; + } + valexp.segment++; + eitems = 0; + ep = valexp.value; + memset(ep, 0, 128); + } + memcpy(ep, p, 4); + eitems++; + ep += 4; + } + p += 4; + } + } else { /* ITEM property */ + if (sizeof(NETVAL) != write(fd, v, sizeof(NETVAL))){ + errorp(1, errstr, "writeerror on %s", tmpfn); + propok=0; + break; + } + } + } + } /* while */ + + if (is_set && eitems) { + if (sizeof(NETVAL) != write(fd, &valexp, sizeof(NETVAL))){ + errorp(1, errstr, "writeerror on %s", tmpfn); + propok=0; + break; + } + } + } /* while */ + } + dbmclose(); + close(fd); + if (propok) + fd=open(tmpfn, O_RDONLY); + else + fd=-1; + } + if (fd > -1) { + NETVAL val; + sync_dbm(); + create_nw_db(dbm_fn[FNVAL], 1); /* creat new value.dbm */ + if (!dbminit(FNVAL)){ + while (sizeof(NETVAL) == read(fd, &val, sizeof(NETVAL))){ + key.dsize = NETVAL_KEY_SIZE; + key.dptr = (char*)&val; + data.dsize = sizeof(NETVAL); + data.dptr = (char*)&val; + if (store(key, data)) { + errorp(0, errstr, "Cannot store obj_id=0x%8x, prop_id=0x%x", + (int)val.obj_id, (int)val.prop_id); + } + } /* while */ + } else { + errorp(1, errstr, "fatal error bindery file %s saved.", + dbm_fn[FNVAL]); + exit(1); + } + dbmclose(); + close(fd); + unlink(tmpfn); + } + } + dbmclose(); + } + sync_dbm(); + xfree(prop_oid); + xfree(props); + xfree(props_fl); + XDPRINTF((1,0, "%s ends after %ld seconds.", errstr, + (long) time(NULL) - tstart)); +} + int nw_fill_standard(char *servername, ipxAddr_t *adr) /* fills the standardproperties */ { + int is_nwe_start = (NULL != servername && NULL != adr); char serverna[MAX_SERVER_NAME+2]; uint32 su_id = 0x00000001; uint32 ge_id = 0x01000001; uint32 server_id= 0x03000001; uint32 q1_id = 0x0E000001; uint32 ps1_id = 0x0F000001; - FILE *f = open_nw_ini(); + int entry18_flags=0; /* for queue handling */ + FILE *f; int auto_ins_user = 0; char auto_ins_passwd[100]; int make_tests = 1; char sysentry[256]; sysentry[0] = '\0'; + + if (is_nwe_start) { + int i = get_ini_int(16); + if (i > -1) make_tests=i; + if (make_tests > 1) + check_compress_bindery(); + } + ge_id = nw_new_obj_prop(ge_id, "EVERYONE", 0x2, 0x0, 0x31, - "GROUP_MEMBERS", P_FL_SET, 0x31, - NULL, 0, 0); - if (f){ + pn_group_members, P_FL_SET, 0x31, + NULL, 0, 0); + if (NULL != (f= open_nw_ini())){ char buff[256]; int what; while (0 != (what =get_ini_entry(f, 0, (char*)buff, sizeof(buff)))) { @@ -1998,6 +2418,10 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) } else if (8 == what) { /* entry8_flags */ entry8_flags = hextoi((char*)buff); + } else if (17 == what) { /* entry17_flags */ + entry17_flags = hextoi((char*)buff); + } else if (18 == what) { /* entry18_flags */ + entry18_flags = hextoi((char*)buff); } else if (21 == what) { /* QUEUES */ char name[200]; char directory[200]; @@ -2041,38 +2465,18 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) } else if (22 == what) { /* PSERVER */ char name[200]; char queue[200]; - char *p=buff; - char *pp=name; - char c; - int state=0; - name[0]='\0'; - queue[0]='\0'; - - while (0 != (c = *p++)) { - if (c == 32 || c == '\t') { - if (!(state & 1)) { - *pp = '\0'; - state++; - } - } else { - if (state & 1){ - if (state == 1) { - pp=queue; - state++; - } else break; - } - *pp++ = c; - } - } - *pp='\0'; - + char sflags[200]; + int flags=0; + int count=sscanf((char*)buff, "%s %s %s", name, queue, sflags); + if (count > 2) flags=hextoi(sflags); + if (count < 2) *queue=0; + if (count < 1) *name=0; if (*name) { upstr(name); upstr(queue); - add_pr_server(ps1_id, name, queue, su_id, ge_id); - ps1_id++; + add_pr_server(ps1_id, name, queue, su_id, ge_id, flags&1 ?1:0); + if (!(flags&1)) ps1_id++; } - } else if (12 == what || 13 == what || 14 == what) { /* SUPERVISOR, OTHERS and GROUPS*/ char nname[100]; @@ -2082,6 +2486,10 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) int flags=0; int set_flags=0; int anz=sscanf((char*)buff, "%s %s %s %s", nname, uname, password, flagsstr); + if (anz == 1) { + strcpy(uname, nname); + anz++; + } if (anz > 1) { upstr(nname); if (anz > 2) { @@ -2123,19 +2531,17 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) fclose(f); } - - - if (servername && adr) { + if (is_nwe_start) { strmaxcpy(serverna, servername, MAX_SERVER_NAME); upstr(serverna); nw_new_obj_prop(server_id, serverna, 0x4, O_FL_DYNA, 0x40, - "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, - (char*)adr, sizeof(ipxAddr_t), 1); + "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, + (char*)adr, sizeof(ipxAddr_t), 1); #ifdef _MAR_TESTS_1 nw_new_obj_prop(pserv_id, serverna, 0x47, O_FL_DYNA, 0x31, - "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, - (char*)adr, sizeof(ipxAddr_t), 1); + "NET_ADDRESS", P_FL_ITEM | P_FL_DYNA, 0x40, + (char*)adr, sizeof(ipxAddr_t), 1); #endif } @@ -2190,14 +2596,16 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) if (*sysentry) { uint8 unixname[512]; uint8 sysname[256]; - int result = get_sys_unixname(unixname, sysname, sysentry); - int downshift = (result & 1); - int unlen = strlen(unixname); + int result = get_sys_unixname(unixname, sysname, sysentry); + int downshift = (result & 1); + int has_trustee = (result & 2); + int unlen = strlen(unixname); if (result < 0) return(-1); new_str(sys_unixname, unixname); new_str(sys_sysname, sysname); - sys_downshift = downshift; - sys_unixnamlen = unlen; + sys_downshift = downshift; + sys_has_trustee = has_trustee; + sys_unixnamlen = unlen; if (make_tests) { uint32 objs[LOC_MAX_OBJS]; @@ -2205,11 +2613,13 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) int ocount=0; uint8 *pp = unixname+unlen; uint8 *ppp = maildir+unlen; + int mask; memcpy(maildir, unixname, unlen+1); test_add_dir(unixname, pp, 4, downshift,0755, 0,0, "LOGIN"); - test_add_dir(unixname, pp, 0, downshift,0755, 0,0, "SYSTEM"); - test_add_dir(unixname, pp, 0, downshift,0755, 0,0, "PUBLIC"); + test_add_dir(unixname, pp, 0, downshift,0751, 0,0, "SYSTEM"); + mask = (sys_has_trustee) ? 0751 : 0755; + test_add_dir(unixname, pp, 0, downshift,mask, 0,0, "PUBLIC"); /* ----- */ ppp=test_add_dir(maildir, ppp, 1, downshift,0755, 0,0, "MAIL"); test_add_dir(maildir, ppp, 0, downshift,0755, 0,0, "USER"); @@ -2233,22 +2643,12 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) obj.id = objs[ocount]; nw_get_obj(&obj); if (obj.type == 1) { - char sx[20]; int gid; int uid; - sprintf(sx, "../%x", (int)obj.id); - if (!get_guid(&gid, &uid, obj.id, NULL)) { - test_add_dir(maildir, ppp, 2, downshift, 0733, gid, uid, sx+3); - memcpy(ppp, "user/", 5); - strmaxcpy(ppp+5, obj.name, 47); - if (downshift) downstr(ppp+5); - else upstr(ppp); - unlink(maildir); - symlink(sx, maildir); - *ppp='\0'; - } else - errorp(0, "Cannot get unix uid/gid", "User=`%s`", obj.name); - + if (!get_guid(&gid, &uid, obj.id, NULL)) + correct_user_dirs(obj.id, obj.name, uid, gid); + else + errorp(10, "Cannot get unix uid/gid", "User=`%s`", obj.name); } else if (obj.type == 3) { /* print queue */ uint8 buff[300]; char *p; @@ -2257,19 +2657,23 @@ int nw_fill_standard(char *servername, ipxAddr_t *adr) if (result > -1 && NULL != (p=strchr(buff, ':')) ) { *p++='\0'; if (!strcmp(buff, sysname)) { - test_add_dir(unixname, pp, 2|4, downshift, 0775, 0, 0, p); + mask = (sys_has_trustee) ? 0751 : 0755; + test_add_dir(unixname, pp, 2|4, downshift, mask, 0, 0, p); } else - errorp(0, "queue dir not on SYS", + errorp(10, "queue dir not on SYS", "Queue=%s, Volume=%s", obj.name, sysname); } else - errorp(0, "Cannot get queue dir", "Queue=%s", obj.name); + errorp(10, "Cannot get queue dir", "Queue=%s", obj.name); } } + } - if (servername && adr) { + + if (is_nwe_start) { /* do only init_queues when starting nwserv */ - init_queues(); /* nwqueue.c */ + init_queues(entry18_flags); /* nwqueue.c */ } + return(0); } return(-1); @@ -2290,22 +2694,21 @@ static void nw_init_dbm_1(char *servername, ipxAddr_t *adr) create_nw_db(dbm_fn[FNOBJ], 0); create_nw_db(dbm_fn[FNPROP], 0); create_nw_db(dbm_fn[FNVAL], 0); - create_nw_db(dbm_fn[FNIOBJ], 0); if (!dbminit(FNOBJ)){ for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr) { - NETOBJ *obj=(NETOBJ*)data.dptr; - if ((obj->flags & O_FL_DYNA) || !obj->name[0]) { - /* dynamic or without name */ - objs[anz++] = obj->id; - if (anz == LOC_MAX_OBJS) break; + NETOBJ *obj=(NETOBJ*)data.dptr; + if ((obj->flags & O_FL_DYNA) || !obj->name[0]) { + /* dynamic or without name */ + objs[anz++] = obj->id; + if (anz == LOC_MAX_OBJS) break; } else if (obj->type == 1 /* && obj->id != 1 */ && obj->security != 0x31) { /* this is for correcting wrong obj security */ obj->security=0x31; - (void)store(key, data); + (void)store(key, data); XDPRINTF((1,0, "Correcting access obj_id=0x%x(%s)", (int)obj->id, obj->name)); } @@ -2320,12 +2723,12 @@ static void nw_init_dbm_1(char *servername, ipxAddr_t *adr) for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { data = fetch(key); if (data.dptr) { - NETPROP *prop=(NETPROP*)data.dptr; - if (prop->flags & P_FL_DYNA) { /* dynamic */ - objs[anz] = prop->obj_id; - props[anz++] = prop->id; - if (anz == LOC_MAX_OBJS) break; - } + NETPROP *prop=(NETPROP*)data.dptr; + if (prop->flags & P_FL_DYNA) { /* dynamic */ + objs[anz] = prop->obj_id; + props[anz++] = prop->id; + if (anz == LOC_MAX_OBJS) break; + } } } } @@ -2613,3 +3016,205 @@ int do_import_dbm(char *path) return(result); } + +/* export functions to export bindery to directory entries */ + +static char *path_bindery = "/var/nwserv/bind"; + +static void bcreate_obj(uint32 id, char *name, int type, + int flags, int security) + +{ + char buf[300]; + char buf1[300]; + uint8 buf_uc[4]; + char id_buf[30]; + int len = slprintf(buf, sizeof(buf)-1,"%s/%x", path_bindery, type); + int idlen; + + U32_TO_BE32(id, buf_uc); + idlen = slprintf(id_buf, sizeof(id_buf)-1,"%x/%x/%x/%x", + (int) buf_uc[0], + (int) buf_uc[1], + (int) buf_uc[2], + (int) buf_uc[3]); + + /* 1 creat */ + nwdbm_mkdir(buf, 0755, 1); + + /* 1/mstover unlink */ + slprintf(buf+len, sizeof(buf)-1-len,"/%s", name); + downstr(buf+len); + unlink(buf); + + /* 1/mstover -> ../id/1/2/3/4 */ + slprintf(buf1,sizeof(buf1)-1, "../id/%s", id_buf); + symlink(buf1, buf); + + /* id/1/2/3/4 creat */ + len = slprintf(buf, sizeof(buf)-2,"%s/id/%s", path_bindery, id_buf); + unx_xrmdir(buf); /* remove if exist */ + nwdbm_mkdir(buf, 0755, 1); + buf[len++] = '/'; + /* ----------------------------------- */ + + /* name -> mstover */ + strmaxcpy(buf+len, "name.o", sizeof(buf)-1-len); + strmaxcpy(buf1, name, sizeof(buf1)-1); + downstr(buf1); + symlink(buf1, buf); + + /* typ -> 1 */ + strmaxcpy(buf+len, "typ.o", sizeof(buf)-1-len); + slprintf(buf1, sizeof(buf1)-1,"%x", type); + symlink(buf1, buf); + + /* flags & security */ + strmaxcpy(buf+len, "f+s.o", sizeof(buf)-1-len); + slprintf(buf1, sizeof(buf1)-1,"%02x%02x", flags&0xff, security&0xff); + symlink(buf1, buf); + +} + +static int export_obj_to_dir(void) +{ + int result = 0; + if (!result) { + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETOBJ *o=(NETOBJ*)data.dptr; + bcreate_obj( o->id, o->name, (int) o->type, + (int)o->flags, (int) o->security); + } + } + } + return(result); +} + +static void bcreate_prop(uint32 id, int prop_id, char *name, + int propflags, int propsecurity) +{ + char buf[300]; + char buf1[300]; + uint8 buf_uc[4]; + + int len; + int len1; + U32_TO_BE32(id, buf_uc); + len = slprintf(buf, sizeof(buf)-1,"%s/id/%x/%x/%x/%x/", + path_bindery, + (int) buf_uc[0], + (int) buf_uc[1], + (int) buf_uc[2], + (int) buf_uc[3]); + + /* prop_id unlink */ + slprintf(buf+len, sizeof(buf)-1-len,"%x.p", prop_id); + downstr(buf+len); + unlink(buf); + + /* id.p -> name */ + slprintf(buf1,sizeof(buf1)-1, "%s", name); + downstr(buf1); + symlink(buf1, buf); + + + /* x/name creat */ + len1 = slprintf(buf+len, sizeof(buf)-1-len,"%s", name); + downstr(buf+len); + unx_xrmdir(buf); /* remove if exist */ + nwdbm_mkdir(buf, 0700, 1); + len += len1; + buf[len++] = '/'; + + /* flags & security */ + strmaxcpy(buf+len, "f+s", sizeof(buf)-1-len); + slprintf(buf1, sizeof(buf1)-1,"%02x%02x", propflags&0xff, propsecurity&0xff); + symlink(buf1, buf); + +} + +static int export_prop_to_dir(void) +{ + int result = 0; + if (!result) { + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETPROP *p=(NETPROP*)data.dptr; + bcreate_prop(p->obj_id, (int) p->id, p->name, + (int)p->flags, (int) p->security); + } + } + } + return(result); +} + + +static void bcreate_val(uint32 id, int prop_id, int segment, + uint8 *value) +{ + char buf[300]; + char buf1[300]; + uint8 buf_uc[4]; + + int len; + int k = 128; + uint8 *p = value; + uint8 *p1 = buf1; + + U32_TO_BE32(id, buf_uc); + len = slprintf(buf, sizeof(buf)-1,"%s/id/%x/%x/%x/%x/%x.p/%x", + path_bindery, + (int) buf_uc[0], + (int) buf_uc[1], + (int) buf_uc[2], + (int) buf_uc[3], + prop_id, + segment); + + /* segment unlink */ + unlink(buf); + while (k--) { + sprintf(p1, "%02x", (int) *p++); + p1+=2; + } + symlink(buf1, buf); +} + + +static int export_val_to_dir(void) +{ + int result = 0; + if (!result) { + for (key = firstkey(); key.dptr != NULL; key = nextkey(key)) { + data = fetch(key); + if (data.dptr) { + NETVAL *v=(NETVAL*)data.dptr; + bcreate_val(v->obj_id, (int)v->prop_id, (int) v->segment, v->value); + } + } + } + return(result); +} + +int do_export_dbm_to_dir(void) +{ + int result =dbminit_ro(FNOBJ); + if (!result) { + export_obj_to_dir(); + result = dbminit_ro(FNPROP); + } + if (!result) { + export_prop_to_dir(); + result = dbminit_ro(FNVAL); + } + if (!result) + export_val_to_dir(); + return(result); +} + + + + diff --git a/nwdbm.h b/nwdbm.h index ff770f9..5234ad2 100644 --- a/nwdbm.h +++ b/nwdbm.h @@ -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 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 diff --git a/nwfile.c b/nwfile.c index 7d1f5e6..280cf31 100644 --- a/nwfile.c +++ b/nwfile.c @@ -1,5 +1,5 @@ -/* nwfile.c 01-Feb-98 */ -/* (C)opyright (C) 1993,1998 Martin Stover, Marburg, Germany +/* nwfile.c 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 @@ -16,24 +16,33 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* history since 21-Apr-00 + * + * mst:25-Apr-00: nw_get_count_open_files() + * + */ + + #include "net.h" #include #include #include +#include #include "nwvolume.h" #include "nwshare.h" #include "nwfile.h" #include "connect.h" #include "nwattrib.h" +#include "trustee.h" #include "nwconn.h" #include "unxfile.h" # include -static got_sig_bus=0; +static int got_sig_bus=0; void sig_bus_mmap(int rsig) { got_sig_bus++; @@ -41,6 +50,7 @@ void sig_bus_mmap(int rsig) signal(SIGBUS, sig_bus_mmap); } + static FILE_HANDLE file_handles[MAX_FILE_HANDLES_CONN]; #define HOFFS 0 #define USE_NEW_FD 1 @@ -50,13 +60,13 @@ static int count_fhandles=0; static int last_fhandle=HOFFS; #endif -static int new_file_handle(uint8 *unixname, int task) +static int new_file_handle(int volume, uint8 *unixname, int task) { -#if USE_NEW_FD +#if USE_NEW_FD int fhandle= -1 + last_fhandle++; #else int fhandle=HOFFS-1; -#endif +#endif FILE_HANDLE *fh=NULL; while (++fhandle < count_fhandles) { fh=&(file_handles[fhandle]); @@ -71,7 +81,7 @@ static int new_file_handle(uint8 *unixname, int task) fh=&(file_handles[count_fhandles]); fhandle = ++count_fhandles; } else { -#if USE_NEW_FD +#if USE_NEW_FD last_fhandle=HOFFS+1; fhandle=HOFFS-1; while (++fhandle < count_fhandles) { @@ -95,9 +105,12 @@ static int new_file_handle(uint8 *unixname, int task) fh->tmodi = 0L; fh->modified = 0; fh->st_ino = 0; - strcpy((char*)fh->fname, (char*)unixname); + fh->access = 0; + fh->inuse = 0; + xstrcpy(fh->fname, (char*)unixname); fh->fh_flags = 0; fh->f = NULL; + fh->volume = volume; XDPRINTF((5, 0, "new_file_handle=%d, count_fhandles=%d, fn=%s", fhandle, count_fhandles, unixname)); return(fhandle); @@ -118,13 +131,18 @@ static int free_file_handle(int fhandle) fh->p_mmap = NULL; fh->size_mmap = 0; } + if (fh->st_ino) { + /* changed by: Ingmar Thiemann */ + share_unlock_all( fh->st_dev, fh->st_ino, fh->fd ); + } close(fh->fd); if (fh->st_ino) { - share_file(fh->st_dev, fh->st_ino, 0); + /* changed by: Ingmar Thiemann */ + share_file(fh->st_dev, fh->st_ino, fh->access&0xff, 0); if (fh->modified) { fh->modified=0; -#if NEW_ATTRIB_HANDLING - set_nw_archive_bit(fh->st_dev, fh->st_ino); +#if NEW_ATTRIB_HANDLING + set_nw_archive_bit(fh->volume, fh->fname, fh->st_dev, fh->st_ino); #endif } } @@ -134,12 +152,14 @@ static int free_file_handle(int fhandle) /* now set date and time */ struct utimbuf ut; ut.actime = ut.modtime = fh->tmodi; + seteuid(0); utime(fh->fname, &ut); + reseteuid(); fh->tmodi = 0L; } } fh->fd = -1; -#if !USE_NEW_FD +#if !USE_NEW_FD while (count_fhandles > fhandle && file_handles[count_fhandles-1].fd == -1 && !(file_handles[count_fhandles-1].fh_flags & FH_DO_NOT_REUSE) ) { @@ -164,42 +184,74 @@ void init_file_module(int task) while (k++ < count_fhandles) free_file_handle(k); count_fhandles = HOFFS; -#if USE_NEW_FD +#if USE_NEW_FD last_fhandle = HOFFS; #endif } else { /* I hope next is ok, added 20-Oct-96 ( 0.98.pl5 ) */ while (k++ < count_fhandles) { FILE_HANDLE *fh=&(file_handles[k-1]); - if (fh->task == task) { + if (fh->task == task && fh->fd>-1) { + MDEBUG(D_FH_OPEN, { + char fname[400]; + int r=fd_2_fname(k, fname, sizeof(fname)); + xdprintf(1,0,"init_file_m fd=%3d, task=%d, fn=`%s`,r=%d", + k, task, fname, r); + }) free_file_handle(k); } } } } -static int xsetegid(gid_t gid) +static int open_with_root_access(char *path, int mode) +/* open existing files */ { - int result = -1; - if (!seteuid(0)) { - if (setegid(gid)) { - XDPRINTF((2, 0, "Cannot change eff Group ID to %d", gid)); - } else - result=0; - if (seteuid(act_uid)) { - reset_guid(); - result = -1; + int fd = open(path, mode); + if (fd < 0 && errno == EACCES) { + seteuid(0); + fd = open(path, mode); + reseteuid(); + } + return(fd); +} + +#if 0 /* not used */ +static int reopen_file(int volume, uint8 *unixname, struct stat *stbuff, + int access, int task) +/* look for file already open and try to use it */ +/* do not know whether this is real ok */ +{ + int fhandle=-1; + int result=0; + while (++fhandle < count_fhandles) { + FILE_HANDLE *fh=&(file_handles[fhandle]); + if (fh->fd > -1 && fh->task == task && fh->volume == volume + && fh->st_dev == stbuff->st_dev && fh->st_ino == stbuff->st_ino) { + if ((fh->access&4) && (access&4)) + return(-0x80); /* share error */ + if ((fh->access&8) && (access&8)) + return(-0x80); /* share error */ + /* changed by: Ingmar Thiemann */ + result=share_file(stbuff->st_dev, stbuff->st_ino, fh->access&0xff, 1); + if (result) + return(-0x80); /* share error */ + if ((fh->access&2) || (access&2)) + return(0); + fh->inuse++; + return(++fhandle); } } - return(result); + return(0); } +#endif int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, int attrib, int access, int creatmode, int task) /* - * creatmode: 0 = open - * | 1 = creat (ever) - * | 2 = creatnew ( creat if not exist ) + * creatmode: 0 = open ( do not creat ) + * | 1 = creat ( creat always ) + * | 2 = creatnew ( creat if not exist else error ) * --------- * & 4 == save handle (not reuse) * & 8 == ignore rights (try to open as root) @@ -225,254 +277,292 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, * */ { - int fhandle = new_file_handle(unixname, task); - int dowrite = ((access & 2) || (creatmode & 3) ) ? 1 : 0; - if (fhandle > HOFFS){ - FILE_HANDLE *fh=&(file_handles[fhandle-1]); - int completition = 0; /* first ok */ - int voloptions = get_volume_options(volume); - int acc = (!stat(fh->fname, stbuff)) - ? get_real_access(stbuff) : -1; - int did_grpchange = 0; - - if (dowrite && (acc > -1) && (acc & W_OK) && !(creatmode&0x8) && - (get_nw_attrib_dword(stbuff, voloptions) & FILE_ATTR_R)) - completition = -0x94; - else if (dowrite && (voloptions & VOL_OPTION_READONLY)) { - completition = (creatmode&3) ? -0x84 : -0x94; - } else if (acc > -1) { - /* do exist */ - if (!S_ISDIR(stbuff->st_mode)) { - if (!(voloptions & VOL_OPTION_IS_PIPE) - || S_ISFIFO(stbuff->st_mode) ) { - /* We look for normal file accesses */ - if (creatmode & 2) { - XDPRINTF((5,0,"CREAT File exist!! :%s:", fh->fname)); - completition = -0x85; /* No Priv */ - } else if (dowrite && !(acc & W_OK) && !(creatmode & 0x8) ) { - if (!S_ISFIFO(stbuff->st_mode)) { - if (entry8_flags&2 && (acc & R_OK)) { - /* we use strange compatibility modus */ - dowrite=0; - XDPRINTF((1, 0, "Uses strange open comp. mode for file `%s`", - fh->fname)); - } else - completition = (creatmode&3) ? -0x84 : -0x94; - } else - completition = (creatmode&3) ? -0x84 : -0x94; - } else if (!(acc & R_OK) && !(creatmode & 0x8) ) - completition = -0x93; + /* int dowrite = ((access & 2) || (creatmode & 3) ) ? 1 : 0; */ + int dowrite; + int completition = 0; /* first ok */ + int fhandle = -1; + int voloptions = get_volume_options(volume); + int volnamlen = get_volume_unixnamlen(volume); + int exist = stat(unixname, stbuff) ? 0 : 1; + int eff_rights = 0; + uint32 dwattrib; - if ((!completition) && !S_ISFIFO(stbuff->st_mode) && dowrite){ - /* is this file already opened write deny by other process */ - if (-1 == share_file(stbuff->st_dev, stbuff->st_ino, 0x12|0x8)) + if ( !(access&3) ) + access |= 3; /* mst:04-Apr-00, default RW */ + + dowrite = ((access & 2) || (creatmode & 3) ) ? 1 : 0; + + /* first we test accesses + * if something is wrong completition will become != 0 + */ + + if (!exist) { + /* we do it again as root to get always the correct information */ + seteuid(0); + exist = stat(unixname, stbuff) ? 0 : 1; + reseteuid(); + } + +#if 0 /* mst:04-Apr-00, not needed here */ + if ((!access) && dowrite){ /* create without access set */ + access = 2; /* OK ? mst: 28-Sep-99 */ + XDPRINTF((2,0,"file_creat_open creatmode=%d, access=0, fn=%s", + creatmode, unixname)); + } +#endif + + if (exist) { /* file exists */ + if (S_ISDIR(stbuff->st_mode)) + completition = -0xff; /* directory is total wrong here */ + else { + eff_rights = tru_get_eff_rights(volume, unixname, stbuff); + dwattrib = get_nw_attrib_dword(volume, unixname, stbuff); + + /* mst: 12-Apr-00 */ + if (access & 0x10) { + access &= ~0x10; + if (!(dwattrib & FILE_ATTR_SHARE)) { + access |= 0x8; /* deny write */ + if (access & 2) + access |= 0x4; /* deny read */ + } + } + +#if 0 + if ( (dwattrib & FILE_ATTR_SHARE) && (access & 0x10) ) { + access &= ~0x10; + if (dowrite) + access |= 0x8; + } +#endif + +#if 0 /* deaktivated in 0.99.pl16, 23-May-99 */ + /* because reopen_file do not handle share conditions correct */ + if (!(creatmode&1) && !(voloptions & VOL_OPTION_IS_PIPE)) { + int fdx=reopen_file(volume, unixname, stbuff, access, task); + if (fdx != 0) + return(fdx); + } +#endif + + if (creatmode&0x2) { /* creat if not exist */ + if (S_ISFIFO(stbuff->st_mode)||(voloptions&VOL_OPTION_IS_PIPE)) { + /* fifo or pipe command always must exist */ + if ((dwattrib&FILE_ATTR_R)||!(eff_rights & TRUSTEE_W)){ + completition = -0x94; /* No write rights */ + } + } else { + XDPRINTF((5,0,"CREAT File exist!! :%s:", unixname)); + completition = -0x85; /* No Priv */ + } + } else if (creatmode&0x1) { /* creat always*/ + if (!(creatmode&0x8)){ + if ((dwattrib&FILE_ATTR_R) + || !(eff_rights & TRUSTEE_W)) + completition = -0x86; /* creat file exists ro */ +#if 0 // mst:14-Apr-00, for create no delete rights are necessary !? + else if (!(eff_rights & TRUSTEE_E)) + completition = -0x85; /* creat file no delete rights */ +#endif + else if (!(eff_rights & TRUSTEE_C)){ + completition = -0x84; /* No creat rights */ + } + } + } else { /* open */ + if (dowrite) { + if (!(creatmode&0x8)) { + if ((dwattrib&FILE_ATTR_R)||!(eff_rights & TRUSTEE_W)){ + if ((entry8_flags&2) && (eff_rights & TRUSTEE_R) ) { + /* we use strange compatibility modus if file is readable */ + dowrite=0; + XDPRINTF((1, 0, "Uses strange open comp. mode for file `%s`", + unixname)); + } else + completition = -0x94; /* No write rights */ + } + } + } else { /* open to read */ + if (!(creatmode&0x8)) { + if (!(eff_rights & TRUSTEE_R)){ + completition = -0x93; /* No read rights */ + } + } + } + } + if ( (!completition) && dowrite && !S_ISFIFO(stbuff->st_mode) && + !(voloptions&VOL_OPTION_IS_PIPE)) { + /* is this file already opened write deny by other process */ + /* changed by: Ingmar Thiemann */ + /* if (-1 == share_file(stbuff->st_dev, stbuff->st_ino, 0x2, 2)) */ + /* pcz: 14-Nov-99 */ + if (-1 == share_file(stbuff->st_dev, stbuff->st_ino, access&0xff, 2)) completition=-0x80; - } + } + } + } else { /* do not exist, must be created */ + if (voloptions&VOL_OPTION_IS_PIPE) + completition=-0xff; /* pipecommands always must exist */ + else if (creatmode&0x3) { /* do creat */ + uint8 *p=(uint8*)strrchr(unixname, '/'); + if (NULL != p && ((p - unixname)+1) >= volnamlen ) { /* parent dir */ + *p='\0'; + seteuid(0); + completition=stat(unixname, stbuff); + reseteuid(); + if (!completition) { + eff_rights = tru_get_eff_rights(volume, unixname, stbuff); + dwattrib = get_nw_attrib_dword(volume, unixname, stbuff); + if (creatmode&0x8) + eff_rights |= TRUSTEE_C|TRUSTEE_W|TRUSTEE_R; + if (!(eff_rights & TRUSTEE_C)){ /* no creat rights */ + completition=-0x84; + } + } else + completition=-0x9c; + *p='/'; + } else + completition=-0x9c; + if (completition==-0x9c) + errorp(0, "nwfile.c", "LINE=%d, unixname='%s', p-unx=%d, volnamlen=%d", + __LINE__, unixname, (p) ? (int)(p - unixname): 0, volnamlen ); + } else + completition=-0xff; /* should, but do not exist */ + } - } else if (acc & X_OK) { - /* special Handling for PIPE commands */ - if (!(acc & W_OK)) { - if (acc & 0x10) /* access owner */ - stbuff->st_mode |= S_IWUSR; - else if (acc & 0x20) /* access group */ - stbuff->st_mode |= S_IWGRP; - else - stbuff->st_mode |= S_IWOTH; - } - } else { - XDPRINTF((4, 0, "No PIPE command rights st_mode=0x%x uid=%d, gid=%d", - stbuff->st_uid, stbuff->st_gid)); - completition = -0xff; - } - } else - completition= -0xff; - } else if ( (voloptions & VOL_OPTION_IS_PIPE) || !(creatmode&3) ) { - /* must exist, but don't */ - completition=-0xff; - } else { - /* File do not exist yet, but must be created */ - char *p=strrchr(unixname, '/'); - /* first we say: not OK */ - completition = -0xff; - if (p) { - *p='\0'; - acc = (!stat(unixname, stbuff)) - ? get_real_access(stbuff) : -1; - if (acc > 0) { - if (acc & W_OK) /* we need write access for this directory */ - completition=0; - else - completition=-0x84; /* no creat rights */ - } - *p='/'; - } - if (completition && (creatmode & 8)) { - acc=0; - completition=0; - } - } + /* + * Here all access tests are made and we can do the open as + * root (open_with_root_access). + */ + if (!completition) { + fhandle = new_file_handle(volume, unixname, task); + if (fhandle > HOFFS) { + FILE_HANDLE *fh=&(file_handles[fhandle-1]); + if (exist) { + if (S_ISFIFO(stbuff->st_mode)) { /* named pipes */ + fh->fh_flags |= FH_IS_PIPE; + fh->fd = open_with_root_access(fh->fname, O_NONBLOCK + | (dowrite + ? O_WRONLY + : O_RDONLY)); + if (fh->fd < 0) + completition=-0x9c; + } else if (voloptions & VOL_OPTION_IS_PIPE) { /* 'pipe' volume */ + fh->fh_flags |= FH_IS_PIPE; + fh->fh_flags |= FH_IS_PIPE_COMMAND; + fh->fd=-3; +#if 0 + stbuff->st_mtime = (time(NULL)-255)+(rand()&0xff); + if (!dowrite) + stbuff->st_size = 0x7fff0000 | (rand() & 0xffff); +#else /* 03-Aug-98 better ? */ + stbuff->st_mtime = time(NULL)+1000; + stbuff->st_size = 0x70000000|(stbuff->st_mtime&0xfffffff); +#endif + stbuff->st_atime = stbuff->st_mtime; + } else { /* 'normal' file */ + /* Changed by: Ingmar Thiemann + * always RDWR for doing flock() with F_WRLCK + */ +#if 0 + int acm = O_RDWR; /*(dowrite) ? O_RDWR : O_RDONLY;*/ +#else /* mst: 26-Sep-99, readonly volumes must be opened O_RDONLY */ + int acm = (voloptions & VOL_OPTION_READONLY) ? O_RDONLY : O_RDWR; +#endif + if (dowrite && (creatmode&0x3)) + acm |= O_TRUNC; + fh->fd = open_with_root_access(fh->fname, acm); + if (fh->fd != -1){ + if (acm&O_TRUNC) { + seteuid(0); + stat(fh->fname, stbuff); + reseteuid(); + } + } else + completition=-0x9c; + if (completition==-0x9c) + errorp(0, "nwfile.c", "LINE=%d, unixname='%s'", __LINE__, unixname); + } + } else { /* needs to be created */ + if (nw_creat_node(volume, fh->fname, 2|8)) + completition=-0x9c; + else { + fh->fd = open_with_root_access(fh->fname, O_RDWR); + fh->offd = 0L; + if (fh->fd==-1) + completition=-0x9c; + else { + seteuid(0); + stat(fh->fname, stbuff); + reseteuid(); + } + } + } + if (!completition && !(fh->fh_flags & FH_IS_PIPE)) { + /* We try sharing and mmaping if not a pipe */ + int result=0; + fh->st_dev=stbuff->st_dev; + fh->st_ino=stbuff->st_ino; + /* changed by: Ingmar Thiemann */ + result = share_file(stbuff->st_dev, stbuff->st_ino, access&0xff, 1); + + if (result==-1) { + XDPRINTF((2, 0, "open share failed,fn='%s', access=0x%x, creatmode=0x%x, dowrite=%d", + fh->fname, access, creatmode, dowrite)); + close(fh->fd); + fh->fd = -1; + completition = -0x80; + /* 0.99.pl0 changed -0xfe -> -0x80 */ + } - if ( (!completition) && (acc & 0x20) && (stbuff->st_gid != act_gid)) { - /* here we try a change egid */ - if (xsetegid(stbuff->st_gid)) { - completition = -0x85; /* no privillegs */ - } else { - did_grpchange++; - } - } + if (use_mmap && fh->fd > -1 && !dowrite) { + fh->size_mmap = fh->offd=lseek(fh->fd, 0L, SEEK_END); + if (fh->size_mmap > 0) { + fh->p_mmap = mmap(NULL, + fh->size_mmap, + PROT_READ, + MAP_SHARED, + fh->fd, 0); + if (fh->p_mmap == (uint8*) -1) { + fh->p_mmap = NULL; + fh->size_mmap=0; + } + } + } + } + if (!completition) { + fh->access = access; + if (fh->fd != -1) { + fh->inuse++; + if (!dowrite) + fh->fh_flags |= FH_OPENED_RO; + if (voloptions & VOL_OPTION_READONLY) + fh->fh_flags |= FH_IS_READONLY; + if (creatmode & 4) + fh->fh_flags |= FH_DO_NOT_REUSE; + } + } else { + XDPRINTF((5,0,"OPEN FILE not OK (-0x%x), fh->name:%s: fhandle=%d", + -completition, fh->fname, fhandle)); + free_file_handle(fhandle); + fhandle=completition; + } + if (completition==-0x9c) + errorp(0, "nwfile.c", "LINE=%d, unixname='%s'", __LINE__, unixname); + } else fhandle=-0x81; /* no more File Handles */ + } else fhandle=completition; - if (!completition) { - if (voloptions & VOL_OPTION_IS_PIPE) { - /* <========= this is a PIPE Volume ====================> */ - fh->fh_flags |= FH_IS_PIPE; - if (S_ISFIFO(stbuff->st_mode)){ - fh->fd = open(fh->fname, - O_NONBLOCK | dowrite ? O_RDWR : O_RDONLY); - } else { - fh->fh_flags |= FH_IS_PIPE_COMMAND; - fh->fd=-3; - } - if (fh->fd != -1) { - if (!dowrite) - stbuff->st_size = 0x7fff0000 | (rand() & 0xffff); - (void)time(&(stbuff->st_mtime)); - stbuff->st_atime = stbuff->st_mtime; - if (creatmode & 4) - fh->fh_flags |= FH_DO_NOT_REUSE; - if (did_grpchange) - xsetegid(act_gid); - goto file_creat_open_ret; - } - } else { - /* <========= this is NOT a PIPE Volume ====================> */ - if (creatmode&0x3) { /* creat File */ - int was_ok=0; - fh->fd=-1; - - if (creatmode & 0x2) { /* creatnew */ - XDPRINTF((5,0,"CREAT FILE:%s: Handle=%d", fh->fname, fhandle)); - if (!nw_creat_node(volume, fh->fname, 0)) - was_ok++; - else - completition = -0x84; /* no create Rights */ - } else { - XDPRINTF((5,0,"CREAT FILE, ever with attrib:0x%x, access:0x%x, fh->fname:%s: handle:%d", - attrib, access, fh->fname, fhandle)); - if (!nw_creat_node(volume, fh->fname, - (creatmode & 0x8) ? (2|8) : 2)) - was_ok++; - else - completition = -0x85; /* no delete /create Rights */ - } - if (was_ok) { - fh->fd = open(fh->fname, O_RDWR); - fh->offd = 0L; - stat(fh->fname, stbuff); - } - } else { - /* ======== 'normal' open of file ================ */ - int acm = (dowrite) ? (int) O_RDWR : (int)O_RDONLY; - if (S_ISFIFO(stbuff->st_mode)){ - acm |= O_NONBLOCK; - fh->fh_flags |= FH_IS_PIPE; - if (!dowrite) stbuff->st_size = 0x7fffffff; - (void)time(&(stbuff->st_mtime)); - stbuff->st_atime = stbuff->st_mtime; - } - fh->fd = open(fh->fname, acm); - if (fh->fd < 0 && (creatmode&8)) { - if (did_grpchange) { - xsetegid(act_gid); - did_grpchange=0; - } - seteuid(0); - fh->fd = open(fh->fname, acm); - reset_guid(); - } - XDPRINTF((5,0, "OPEN FILE:fd=%d, attrib:0x%x, access:0x%x, fh->fname:%s:fhandle=%d", - fh->fd, attrib, access, fh->fname, fhandle)); - if (fh->fd < 0) - completition = dowrite ? -0x94 : -0x93; - } + MDEBUG(D_FH_OPEN, { + char fname[200]; + if (!fd_2_fname(fhandle, fname, sizeof(fname))){ + FILE_HANDLE *fh=fd_2_fh(fhandle); + xdprintf(1,0,"Open/creat fd=%3d, task=%d, fn=`%s`, openmode=%s, access=0x%x, no reuse=%d", + fhandle, task, fname, (fh && (fh->fh_flags &FH_OPENED_RO)) ? "RO" : "RW", + access, fh->fh_flags & FH_DO_NOT_REUSE ? 1 :0 ); + } + }) - if (fh->fd > -1) { - if (did_grpchange) { - xsetegid(act_gid); - did_grpchange=0; - } - if (!(fh->fh_flags & FH_IS_PIPE)) { - /* Not a PIPE */ - int result=0; - fh->st_dev=stbuff->st_dev; - fh->st_ino=stbuff->st_ino; - if ( (!result) && ((access & 0x4) || (access & 0x8)) ) { - if (access & 0x4) /* deny read */ - result=share_file(stbuff->st_dev, stbuff->st_ino, 0x5); - if ((access & 0x8) && !result) - result=share_file(stbuff->st_dev, stbuff->st_ino, 0x2); - XDPRINTF(((result==-1)?2:5, 0, "open shared lock:result=%d,fn='%s'", - result, fh->fname)); - } else { - result=share_file(stbuff->st_dev, stbuff->st_ino, 1); - if (result==-1) { - XDPRINTF((2, 0, "open share failed,fn='%s'", fh->fname)); - } - } - if (result==-1) { - close(fh->fd); - fh->fd = -1; - completition = -0x80; - /* 0.99.pl0 changed -0xfe -> -0x80 */ - } - - if (use_mmap && fh->fd > -1 && !dowrite) { - fh->size_mmap = fh->offd=lseek(fh->fd, 0L, SEEK_END); - if (fh->size_mmap > 0) { - fh->p_mmap = mmap(NULL, - fh->size_mmap, - PROT_READ, - MAP_SHARED, - fh->fd, 0); - if (fh->p_mmap == (uint8*) -1) { - fh->p_mmap = NULL; - fh->size_mmap=0; - } - } - } - } - } - if (fh->fd > -1) { - if (did_grpchange) - xsetegid(act_gid); - if (!dowrite) - fh->fh_flags |= FH_OPENED_RO; - if (voloptions & VOL_OPTION_READONLY) - fh->fh_flags |= FH_IS_READONLY; - if (creatmode & 4) - fh->fh_flags |= FH_DO_NOT_REUSE; - goto file_creat_open_ret; - } - } /* else (note pipecommand) */ - } /* if !completition */ - if (did_grpchange) - xsetegid(act_gid); - XDPRINTF((5,0,"OPEN FILE not OK (-0x%x), fh->name:%s: fhandle=%d", - -completition, fh->fname, fhandle)); - free_file_handle(fhandle); - fhandle=completition; - } else fhandle=-0x81; /* no more File Handles */ - -file_creat_open_ret: - MDEBUG(D_FH_OPEN, { - char fname[200]; - if (!fd_2_fname(fhandle, fname, sizeof(fname))){ - FILE_HANDLE *fh=fd_2_fh(fhandle); - xdprintf(1,0,"Open/creat fd=%d, fn=`%s`, openmode=%s", - fhandle, fname, (fh && (fh->fh_flags &FH_OPENED_RO)) ? "RO" : "RW" ); - } - }) - return(fhandle); + return(fhandle); } int nw_set_fdate_time(uint32 fhandle, uint8 *datum, uint8 *zeit) @@ -500,20 +590,52 @@ int nw_set_fdate_time(uint32 fhandle, uint8 *datum, uint8 *zeit) return(-0x88); /* wrong filehandle */ } -int nw_close_file(int fhandle, int reset_reuse) +int nw_close_file(int fhandle, int reset_reuse, int task) { - XDPRINTF((5, 0, "nw_close_file handle=%d, count_fhandles", + XDPRINTF((5, 0, "nw_close_file handle=%d, count_fhandles=%d", fhandle, count_fhandles)); MDEBUG(D_FH_OPEN, { char fname[200]; int r=fd_2_fname(fhandle, fname, sizeof(fname)); - xdprintf(1,0,"nw_close_file: fd=%d, fn=`%s`,r=%d", fhandle, fname, r); + xdprintf(1,0,"nw_close_f fd=%3d, task=%d, fn=`%s`,r=%d, rreuse=%d", + fhandle, task, fname, r, reset_reuse); }) if (fhandle > HOFFS && (fhandle <= count_fhandles)) { FILE_HANDLE *fh=&(file_handles[fhandle-1]); if (reset_reuse) fh->fh_flags &= (~FH_DO_NOT_REUSE); + else if (fh->task != task) { + /* if close file's task is wrong the file will not be closed. + * I hope this is right !? + */ + char fname[200]; + fd_2_fname(fhandle, fname, sizeof(fname)); + xdprintf( (task && fh->task) ? 2 : 3, 0, + "%s close_file fd=%3d, task=%d differs fh->task=%d, fn=`%s`", + (task == 0 || fh->task == 0) ? "do" : "not", + fhandle, task, fh->task, fname); + + /* + * return(0); 24-May-98 , 0.99.pl9 + */ + + /* 21-Oct-98: I think file must be closed always, + * got problem with pserver which opens the file with task =0 + * and closes it with task <> 0. + */ + + /* 23-May-99: 0.99.pl16 we only close file if task = 0 or + * file open task = 0. + */ + + if ( task && fh->task ) + return(0); + } + + if (--fh->inuse > 0) /* 03-Dec-98 */ + return(0); + if (fh->fd > -1 || (fh->fd == -3 && fh->fh_flags & FH_IS_PIPE_COMMAND)) { int result = 0; int result2; @@ -529,13 +651,18 @@ int nw_close_file(int fhandle, int reset_reuse) fh->p_mmap = NULL; fh->size_mmap = 0; } + if (fh->st_ino) { + /* changed by: Ingmar Thiemann */ + share_unlock_all( fh->st_dev, fh->st_ino, fh->fd ); + } result=close(fh->fd); if (fh->st_ino) { - share_file(fh->st_dev, fh->st_ino, 0); + /* changed by: Ingmar Thiemann */ + share_file(fh->st_dev, fh->st_ino, fh->access&0xff, 0); if (fh->modified) { fh->modified=0; -#if NEW_ATTRIB_HANDLING - set_nw_archive_bit(fh->st_dev, fh->st_ino); +#if NEW_ATTRIB_HANDLING + set_nw_archive_bit(fh->volume, fh->fname, fh->st_dev, fh->st_ino); #endif } } @@ -545,7 +672,9 @@ int nw_close_file(int fhandle, int reset_reuse) && !(fh->fh_flags & FH_IS_READONLY)) { struct utimbuf ut; ut.actime = ut.modtime = fh->tmodi; + seteuid(0); utime(fh->fname, &ut); + reseteuid(); fh->tmodi = 0L; } #ifdef TEST_FNAME @@ -586,7 +715,9 @@ int nw_commit_file(int fhandle) if (fh->tmodi > 0L) { struct utimbuf ut; ut.actime = ut.modtime = fh->tmodi; + seteuid(0); utime(fh->fname, &ut); + reseteuid(); fh->tmodi = 0L; } fh->fd=dup2(fd, fh->fd); @@ -598,7 +729,9 @@ int nw_commit_file(int fhandle) if (fh->tmodi > 0L) { struct utimbuf ut; ut.actime = ut.modtime = fh->tmodi; + seteuid(0); utime(fh->fname, &ut); + reseteuid(); } #endif } @@ -627,7 +760,7 @@ static void open_pipe_command(FILE_HANDLE *fh, int dowrite) fh->fname, dowrite ? "WRITE" : "READ", act_connection, act_pid); - fh->f = ext_popen(pipecommand, geteuid(), getegid()); + fh->f = ext_popen(pipecommand, geteuid(), getegid(), 0); } fh->fd = (fh->f) ? fh->f->fds[dowrite ? 0 : 1] : -3; } @@ -641,7 +774,18 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) if (fh->fd > -1) { if (fh->fh_flags & FH_IS_PIPE) { /* PIPE */ int readsize=size; -#if 1 +#if 1 + fd_set fdin; + struct timeval t; + FD_ZERO(&fdin); + FD_SET(fh->fd, &fdin); + t.tv_sec = 5; /* should be enough */ + t.tv_usec = 0; + size = select(fh->fd+1, &fdin, NULL, NULL, &t); + if (size > 0) + size = read(fh->fd, data, readsize); + if (size == -1) size=0; +#elif 1 if (-1 == (size = read(fh->fd, data, readsize)) ) { int k=2; do { @@ -662,27 +806,39 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) size=offset; #endif #if 1 - if (!size) { + if ((fh->fh_flags & FH_IS_PIPE_COMMAND) && !size) { if (fh->f->flags & 1) return(-0x57); fh->f->flags |= 1; } #endif } else if (use_mmap && fh->p_mmap) { - while (1) { - if (offset < fh->size_mmap) { - if (size + offset > fh->size_mmap) - size = fh->size_mmap - offset; - memcpy(data, fh->p_mmap+offset, size); - if (got_sig_bus) { - fh->size_mmap = lseek(fh->fd, 0L, SEEK_END); - got_sig_bus = 0; - } else + /* added by: Ingmar Thiemann + * Netware allows no read/write on locked sections + */ + /* check for lock */ + struct flock flockd; + flockd.l_type = F_WRLCK; + flockd.l_whence = SEEK_SET; + flockd.l_start = offset; + flockd.l_len = size; + fcntl(fh->fd, F_GETLK, &flockd); + if (flockd.l_type == F_UNLCK) { + while (1) { + if (offset < fh->size_mmap) { + if (size + offset > fh->size_mmap) + size = fh->size_mmap - offset; + memcpy(data, fh->p_mmap+offset, size); + if (got_sig_bus) { + fh->size_mmap = lseek(fh->fd, 0L, SEEK_END); + got_sig_bus = 0; + } else + break; + } else { + size=-1; break; - } else { - size=-1; - break; - } - } /* while */ + } + } /* while */ + } else size = -0x93; /* no read privileges */ } else { if (fh->offd != (long)offset) { fh->offd=lseek(fh->fd, offset, SEEK_SET); @@ -691,11 +847,23 @@ int nw_read_file(int fhandle, uint8 *data, int size, uint32 offset) } } if (fh->offd > -1L) { - if ((size = read(fh->fd, data, size)) > -1) { - fh->offd+=(long)size; - } else { - XDPRINTF((5,0,"read-file failed in read")); - } + /* added by: Ingmar Thiemann + * Netware allows no read/write on locked sections + */ + /* check for lock */ + struct flock flockd; + flockd.l_type = F_WRLCK; + flockd.l_whence = SEEK_SET; + flockd.l_start = offset; + flockd.l_len = size; + fcntl(fh->fd, F_GETLK, &flockd); + if (flockd.l_type == F_UNLCK) { + if ((size = read(fh->fd, data, size)) > -1) { + fh->offd+=(long)size; + } else { + XDPRINTF((5,0,"read-file failed in read")); + } + } else size = -0x93; /* no read privileges */ } else size = -1; } if (size == -1) size=0; @@ -742,10 +910,24 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset) fh->offd = lseek(fh->fd, offset, SEEK_SET); if (size) { if (fh->offd > -1L) { - size = write(fh->fd, data, size); - fh->offd+=(long)size; - if (!fh->modified) - fh->modified++; + /* added by: Ingmar Thiemann + * Netware allows no read/write on locked sections + */ + /* check for lock */ + struct flock flockd; + flockd.l_type = F_WRLCK; + flockd.l_whence = SEEK_SET; + flockd.l_start = offset; + flockd.l_len = size; + fcntl(fh->fd, F_GETLK, &flockd); + if (flockd.l_type == F_UNLCK) { + /*if (share_lock( fh->st_dev, fh->st_ino, fh->fd, 2, offset, size ) == 0) {*/ + + size = write(fh->fd, data, size); + fh->offd+=(long)size; + if (!fh->modified) + fh->modified++; + } else size = -0x94; /* no write privileges */ } else size = -1; return(size); } else { /* truncate FILE */ @@ -804,48 +986,60 @@ int nw_server_copy(int qfhandle, uint32 qoffset, return(-0x88); /* wrong filehandle */ } -int nw_lock_file(int fhandle, uint32 offset, uint32 size, int do_lock) +int nw_log_physical_record(int fhandle, uint32 offset, + uint32 size, int lock_flag) { int result=-0x88; /* wrong filehandle */ if (fhandle > HOFFS && (fhandle <= count_fhandles)) { FILE_HANDLE *fh=&(file_handles[fhandle-1]); if (fh->fd > -1) { - struct flock flockd; if (fh->fh_flags & FH_IS_PIPE) { result=0; goto leave; } - flockd.l_type = (do_lock) - ? ((fh->fh_flags & FH_OPENED_RO) ? F_RDLCK - : F_WRLCK) - : F_UNLCK; - flockd.l_whence = SEEK_SET; -#if 0 - flockd.l_start = offset; -#else - /* Hint from:Morio Taneda + /* Changed by: Ingmar Thiemann + * locks must be exclusiv, so it must always be F_WRLCK + * + * Hint from:Morio Taneda * dBase needs it * 03-Dec-96 + * + * flockd.l_start = (offset & 0x7fffffff); + * + * Changed by: Ingmar Thiemann to 0x0fffffff + * Changed by mst: 05-Oct-99 to 0x7fffffff again. + * + * if (size == MAX_U32) + * size = 0; + * This is only a guess, but a size of 0xffffffff means to lock + * the rest of the file, starting from the offset, to do this with + * linux, a size of 0 has to be passed to the fcntl function. + * ( Peter Gerhard ) */ - flockd.l_start = (offset & 0x7fffffff); -#endif + result = share_lock( fh->st_dev, + fh->st_ino, + fh->fd, + (lock_flag < 0) + ? 0 /* remove lock */ + : 1, /* add lock */ + + (lock_flag < 0) + ? lock_flag + : ( (fh->fh_flags & FH_IS_READONLY) + ? 3 /* no exclusiv lock */ + : lock_flag ), - if (size == MAX_U32) { - /* This is only a guess, but a size of 0xffffffff means to lock - * the rest of the file, starting from the offset, to do this with - * linux, a size of 0 has to be passed to the fcntl function. - * ( Peter Gerhard ) - * - */ - flockd.l_len = 0; - } else - flockd.l_len = (size & 0x7fffffff); + offset & 0x7fffffff, - result = fcntl(fh->fd, F_SETLK, &flockd); - XDPRINTF((2, 0, "nw_%s_datei result=%d, fh=%d, offset=%d, size=%d", - (do_lock) ? "lock" : "unlock", result, fhandle, offset, size)); + (size==MAX_U32) + ? 0 + : size & 0x7fffffff); + + XDPRINTF((4, 0, "nw_log_phy_rec:flag=%2d, result=%d, fh=%d, offset=%d, size=%d", + lock_flag, result, fhandle, offset, size)); + if (result) - result= (do_lock) ? -0xfe : -0xff; + result= (lock_flag > -1) ? -0xfe : -0xff; /* 0.99.pl0: changed -0xfd -> -0xfe, hint from Przemyslaw Czerpak */ } else if (fh->fd == -3) result=0; } @@ -853,9 +1047,8 @@ leave: MDEBUG(D_FH_LOCK, { char fname[200]; (void)fd_2_fname(fhandle, fname, sizeof(fname)); - xdprintf(1,0,"nw_%s_datei: fd=%d, fn=`%s`,r=0x%x, offs=%d, len=%d", - (do_lock) ? "lock" : "unlock", - fhandle, fname, -result, offset, size); + xdprintf(1,0,"nw_log_phy_rec:flag=%2d, fd=%d, fn=`%s`,r=0x%x, offs=%d, len=%d", + lock_flag, fhandle, fname, -result, offset, size); }) return(result); @@ -889,29 +1082,249 @@ int get_nwfd(int fhandle) return(-1); } -int nw_unlink(int volume, char *name) +void log_file_module(FILE *f) { - struct stat stbuff; - int voloptions=get_volume_options(volume); - if (voloptions & VOL_OPTION_IS_PIPE) - return(0); /* don't delete 'pipe commands' */ - else if (get_volume_options(volume) & VOL_OPTION_READONLY) - return(-0x8a); /* don't delete 'readonly' */ - if (stat(name, &stbuff)) - return(-0x9c); /* wrong path */ - if (get_nw_attrib_dword(&stbuff, voloptions) & FILE_ATTR_R) - return(-0x8a); /* don't delete 'readonly' */ - - if ( -1 == share_file(stbuff.st_dev, stbuff.st_ino, 0x12|0x8) - || ( !(entry8_flags&0x10) && - -1 == share_file(stbuff.st_dev, stbuff.st_ino, 0x11|0x4)) ) - return(-0x8a); /* NO Delete Privileges, file is shared open */ - if (!unlink(name)) { - free_nw_ext_inode(stbuff.st_dev, stbuff.st_ino); - return(0); + if (f) { + int k=HOFFS-1; + int handles=0; + while (++k < count_fhandles) { + FILE_HANDLE *fh=&(file_handles[k]); + if (fh && fh->fd != -1) { + fprintf(f,"%4d %2d %d %4d 0x%04x 0x%04x %2d '%s'\n", + k+1, fh->inuse, fh->modified, fh->task, + fh->fh_flags, fh->access, fh->volume, + fh->fname); + handles++; + } + } + fprintf(f, "count-open-files:%4d\n" , handles); + fflush(f); } - return(-0x8a); /* NO Delete Privileges */ } +int nw_get_count_open_files(uint8 *handlebuf, uint32 offset) +/* returns max. 100 handles */ +{ + int k = max(HOFFS-1, offset-1); + int handles = 0; + while (handles < 100 && ++k < count_fhandles) { + FILE_HANDLE *fh=&(file_handles[k]); + if (fh && fh->fd != -1) { + handles++; + if (handlebuf) { + U32_TO_BE32(k+1, handlebuf); + handlebuf+=4; + } + } + } + return(handles); +} +/* quick and dirty hack for 0.99.pl17, 25-May-99 */ +typedef struct sLOCK_AREA { + int locks; /* count locks */ + int exclusive; /* exclusive lock ? */ + uint32 offset; + struct sLOCK_AREA *next; +} LOCK_AREA; + +typedef struct sLOCK_FILE { + char *fn; + int fd; + LOCK_AREA *lock_area; + struct sLOCK_FILE *next; +} LOCK_FILE; + +static LOCK_FILE *root_lf=NULL; +static LOCK_FILE *last_lf=NULL; +static LOCK_AREA *last_la=NULL; + +static LOCK_AREA *find_lockarea(LOCK_FILE *lf, uint32 offset) +{ + LOCK_AREA *la=lf->lock_area; + last_la = NULL; + while (la && la->offset != offset) { + last_la=la; + la=la->next; + } + return(la); +} + +static LOCK_FILE *find_lockfile(char *fn) +{ + LOCK_FILE *lf=root_lf; + last_lf = NULL; + while (lf && strcmp(lf->fn, fn)) { + last_lf=lf; + lf=lf->next; + } + return(lf); +} + +int nw_log_logical_record(int lock_flag, + int timeout, + int len, + uint8 *data) +/* + * lock_flag + * -1 = remove lock + * -2 = remove lock + log + * 0 = log + * 1 = lock exclusive + * 3 = shared lock +*/ +{ + static char *path_share_lock_files=NULL; + uint8 fn[256]; + uint8 fullpath[400]; + uint32 offset; + LOCK_FILE *lf = NULL; + LOCK_AREA *la = NULL; + struct flock flockd; + flockd.l_whence = SEEK_SET; + flockd.l_len = 1; + + if (lock_flag != -1) { + if (share_set_logrec_add_rm(lock_flag, timeout, len, data)) + return (-0xff); + } + if (!lock_flag) + return(0); /* log only */ + + if (lock_flag == -1 || lock_flag == -2) + flockd.l_type = F_UNLCK; + else if (lock_flag == 1) + flockd.l_type = F_WRLCK; /* exclusive */ + else if (lock_flag == 3) + flockd.l_type = F_RDLCK; /* shared */ + else + return(-0xfb); + + if (len < 4) { + uint8 buf[4]; + memcpy(buf, data, len); + memset(buf+len, 0, 4 -len); + len = 0; + offset=GET_BE32(buf); + } else { + offset=GET_BE32(data); + len -= 4; + } + + flockd.l_start = offset; + + if (len > 0) { + int i=-1; + if (len > sizeof(fn)) + len = sizeof(fn-1); + memcpy(fn, data+4, len); + while (++i < len) { + if (fn[i]=='/') { + fn[i] = '-'; + if (len < sizeof(fn-1)) + fn[len++] = '_'; + } else if (fn[i] == '\0') { + fn[i] = '_'; + if (len < sizeof(fn-1)) + fn[len++] = '_'; + } + } + fn[len]='\0'; + } else { + strcpy(fn, "GENERIC_LOCKFILE"); + } + + if (NULL==path_share_lock_files) { + char buff[300]; + 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(); + } + + sprintf(fullpath,"%s/%s.k", path_share_lock_files, fn); + + lf = find_lockfile(fn); + + if (!lf) { + int fd; + if (lock_flag < 0) /* unlock */ + return(-0xff); + + seteuid(0); + fd = open(fullpath, O_RDWR|O_CREAT, 0600); + reseteuid(); + + if (fcntl(fd, F_SETLK, &flockd)) + /* already locked by other process */ + return(-0xfe); + + lf=(LOCK_FILE*)xcmalloc(sizeof(LOCK_FILE)); + lf->fd = fd; + new_str(lf->fn, fn); + if (last_lf) + last_lf->next = lf; + else + root_lf = lf; + } + + la = find_lockarea(lf, offset); + + if (!la) { + if (lock_flag < 0) /* unlock */ + return (-0xff); + + if (fcntl(lf->fd, F_SETLK, &flockd)) + /* already locked by other process */ + return(-0xfe); + + la = (LOCK_AREA*)xcmalloc(sizeof(LOCK_AREA)); + la->offset=offset; + if (last_la) + last_la->next = la; + else + lf->lock_area = la; + la->locks++; + if (lock_flag == 1) + la->exclusive++; + } else if (lock_flag > -1) { + if (la->exclusive || lock_flag == 1) + /* already locked */ + return(-0xfe); + la->locks++; + } + + if (lock_flag < 0) { /* remove lock */ + if (--la->locks > 0) + return(0); + (void) fcntl(lf->fd, F_SETLK, &flockd); + if (last_la) + last_la->next = la->next; + else + lf->lock_area = la->next; + xfree(la); + + if (!lf->lock_area) { + /* no more locks by this file */ + close(lf->fd); + +#if 0 /* TODO remove file if it is not opened/locked by other process */ + seteuid(0); + unlink(fullpath); + reseteuid(); +#endif + + xfree(lf->fn); + if (last_lf) + last_lf->next = lf->next; + else + root_lf = lf->next; + xfree(lf); + } + } + return(0); +} diff --git a/nwfile.h b/nwfile.h index 85b315e..06885d9 100644 --- a/nwfile.h +++ b/nwfile.h @@ -1,4 +1,4 @@ -/* nwfile.h 09-Feb-98 */ +/* nwfile.h 10-Nov-99 */ #ifndef _NWFILE_H_ #define _NWFILE_H_ #include "extpipe.h" @@ -15,9 +15,12 @@ typedef struct { int fh_flags; /* 2 = PIPE */ /* 4 = don't reuse after close */ /* 0x20 = readonly */ - int st_dev; /* device */ - int st_ino; /* inode */ + 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 diff --git a/nwqconn.c b/nwqconn.c index b46c2cf..f30bb05 100644 --- a/nwqconn.c +++ b/nwqconn.c @@ -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); } @@ -80,21 +88,23 @@ static INT_QUEUE_JOB *find_queue_job(uint32 queue_id, int job_id) return(NULL); } -static int open_creat_queue_file(int mode, uint8 +static int open_creat_queue_file(int mode, uint8 *file_name, int file_name_len, uint8 *dirname, int dirname_len) /* modes: - * 0 : creat + * 0 : creat * 1 : open ro (as root) * 2 : open rw (as root) */ { 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,27 +114,30 @@ 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]; uint8 fn[300]; strmaxcpy(dn, dirname, dirname_len); strmaxcpy(fn, file_name, file_name_len); - XDPRINTF((1, 0, "open_creat_queue_file, mode=%d,result=-0x%x, dn='%s', fn='%s'", + XDPRINTF((1, 0, "open_creat_queue_file, mode=%d,result=-0x%x, dn='%s', fn='%s'", mode, -result, dn, fn)); result=-0xff; } return(result); } -int creat_queue_job(uint32 q_id, - uint8 *queue_job, +int creat_queue_job(int task, + uint32 q_id, + uint8 *queue_job, uint8 *responsedata, uint8 old_call) { @@ -134,11 +147,11 @@ int creat_queue_job(uint32 q_id, INT_QUEUE_JOB *jo; int result; memcpy(responsedata, queue_job, (old_call) ? sizeof(QUEUE_JOB_OLD) - : sizeof(QUEUE_JOB)); + : sizeof(QUEUE_JOB)); 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) { @@ -148,9 +161,9 @@ int creat_queue_job(uint32 q_id, result = sizeof(QUEUE_JOB_OLD) - 202; } } else { - QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + 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) { @@ -161,8 +174,8 @@ int creat_queue_job(uint32 q_id, } if (result < 0) free_queue_job(q_id, job_id); - - XDPRINTF((6, 0, "creat_q_job, id=%d, result=%d", jo ? jo->job_id : -1, + + XDPRINTF((6, 0, "creat_q_job, id=%d, result=%d", jo ? jo->job_id : -1, result)); return(result); } @@ -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,13 +199,12 @@ 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]; QUEUE_PRINT_AREA qpa; memcpy(&qpa, client_area, sizeof(QUEUE_PRINT_AREA)); - strmaxcpy((uint8*)unixname, + strmaxcpy((uint8*)unixname, (uint8*)file_get_unix_name(jo->fhandle), sizeof(unixname)-1); XDPRINTF((5,0,"nw_close_file_queue fhandle=%d", jo->fhandle)); if (*unixname) { @@ -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++; @@ -232,7 +244,7 @@ int close_queue_job2(uint32 q_id, int job_id, if (0 != (k=ext_pclose(fp))) { XDPRINTF((1,0,"Errorresult = %d by closing print pipe", k)); } - } + } fclose(f); if (is_ok) { seteuid(0); @@ -244,15 +256,17 @@ 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, - uint8 *queue_job, +int service_queue_job(int task, + uint32 q_id, + uint8 *queue_job, uint8 *responsedata, uint8 old_call) { @@ -262,12 +276,12 @@ int service_queue_job(uint32 q_id, INT_QUEUE_JOB *jo; int result; memcpy(responsedata, queue_job, (old_call) ? sizeof(QUEUE_JOB_OLD) - : sizeof(QUEUE_JOB)); + : sizeof(QUEUE_JOB)); 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); - result = open_creat_queue_file(1, + 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); if (result > -1) { @@ -277,9 +291,9 @@ int service_queue_job(uint32 q_id, result = sizeof(QUEUE_JOB_OLD) - 202; } } else { - QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + 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,11 +314,11 @@ 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; } - XDPRINTF((5,0,"finish_abort_queue_job Q=0x%x, job=%d, result=%d", + XDPRINTF((5,0,"finish_abort_queue_job Q=0x%x, job=%d, result=%d", q_id, job_id, result)); return(result); } @@ -312,7 +326,7 @@ int finish_abort_queue_job(uint32 q_id, int job_id) uint32 get_queue_job_fhandle(uint32 q_id, int job_id) { INT_QUEUE_JOB *jo=find_queue_job(q_id, job_id); - if (jo) + if (jo) return(jo->fhandle); return(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)) ;; +} + diff --git a/nwqconn.h b/nwqconn.h index 679edf3..930701b 100644 --- a/nwqconn.h +++ b/nwqconn.h @@ -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 diff --git a/nwqueue.c b/nwqueue.c index 507bc5e..937d08e 100644 --- a/nwqueue.c +++ b/nwqueue.c @@ -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,7 +376,11 @@ static int fill_q_job_entry(INT_QUEUE_JOB *jo, { memset(job->record_in_use, 0xff, 2); memset(job->record_previous, 0, 4); - memset(job->record_next, 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); U32_TO_32(jo->client_task, job->client_task); @@ -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; - return(result); - } - return(-0xff); - } - return(-0xd8); /* queue not active */ + } 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); } 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_list(uint32 q_id, uint32 offset, uint8 *responsedata) +{ + int result = -0xff; + NWE_QUEUE *q = find_queue(q_id); + 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); +} + 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) { - struct stat stb; - uint8 buf[300]; - build_unix_queue_file(buf, q, qj); - if (!stat(buf, &stb)) - return(stb.st_size); - return(0); - } + 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; @@ -570,7 +644,7 @@ int nw_remove_job_from_queue(uint32 user_id, uint32 q_id, int job_id) int result=-0xff; NWE_QUEUE *q = find_queue(q_id); INT_QUEUE_JOB *qj = find_queue_job(q, job_id); - if (qj) { + if (qj) { if (user_id==1 || user_id == qj->client_id) { result=remove_queue_job_file(q, qj); if (!result) @@ -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,53 +752,64 @@ 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) { - uint8 *fulldirname = (old_call) ? responsedata+sizeof(QUEUE_JOB_OLD) - : responsedata+sizeof(QUEUE_JOB); - int len = nw_get_q_dirname(q_id, fulldirname+1); - - if (len > 0) { - INT_QUEUE_JOB *qj=q->queue_jobs; - INT_QUEUE_JOB *fqj=NULL; - time_t acttime=time(NULL); - *fulldirname=(uint8) len++; - *(fulldirname+len)=0; /* for testprints only */ - while(qj) { - if ( (!qj->server_id) - && !(qj->job_control_flags&0x20) /* not actual queued */ - && qj->execute_time <= acttime - && (qj->target_id == MAX_U32 || qj->target_id == user_id) - && (qj->job_typ == MAX_U16 || job_typ==MAX_U16 - || qj->job_typ == job_typ)) { - - fqj=qj; - break; - } 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, - (qj->execute_time > acttime) ? "execute time not reached" : "")); + 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); + + if (len > 0) { + INT_QUEUE_JOB *qj=q->queue_jobs; + INT_QUEUE_JOB *fqj=NULL; + time_t acttime=time(NULL); + *fulldirname=(uint8) len++; + *(fulldirname+len)=0; /* for testprints only */ + while(qj) { + if ( (!qj->server_id) + && !(qj->job_control_flags&0x20) /* not actual queued */ + && qj->execute_time <= acttime + && (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, + (qj->execute_time > acttime) ? "execute time not reached" : "")); + } + qj=qj->next; } - qj=qj->next; - } - if (fqj) { - fqj->server_id = user_id; - fqj->server_station = connection; - fqj->server_task = task; - if (old_call) { - QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; - result=fill_q_job_entry_old(fqj, job, 1); + if (fqj) { + fqj->server_id = user_id; + fqj->server_station = connection; + fqj->server_task = task; + if (old_call) { + QUEUE_JOB_OLD *job=(QUEUE_JOB_OLD*)responsedata; + result=fill_q_job_entry_old(fqj, job, 1); + } else { + QUEUE_JOB *job=(QUEUE_JOB*)responsedata; + result=fill_q_job_entry(fqj, job, 1); + } + result+=len; + XDPRINTF((3, 0, "nw service queue job dirname=`%s`", fulldirname+1)); } else { - QUEUE_JOB *job=(QUEUE_JOB*)responsedata; - result=fill_q_job_entry(fqj, job, 1); + XDPRINTF((3, 0, "No queue job found for q_id=0x%x, user_id=0x%x,job_typ=0x%x", + q_id, user_id, job_typ)); } - result+=len; - XDPRINTF((3, 0, "nw service queue job dirname=`%s`", fulldirname+1)); } else { - XDPRINTF((3, 0, "No queue job found for q_id=0x%x, user_id=0x%x,job_typ=0x%x", - q_id, user_id, job_typ)); + XDPRINTF((1, 0, "Could not get queuedir of q_id=0x%x", q_id)); } - } 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); } } diff --git a/nwqueue.h b/nwqueue.h index a2d7d10..abdf26c 100644 --- a/nwqueue.h +++ b/nwqueue.h @@ -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 diff --git a/nwroute.c b/nwroute.c index dbed9d5..e4aa108 100644 --- a/nwroute.c +++ b/nwroute.c @@ -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); - 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; @@ -475,7 +475,7 @@ void handle_rip(int fd, int ipx_pack_typ, if (is_response) { insert_delete_net(net, GET_BE32(from_addr->net), - from_addr->node, hops, ticks, (hops > 15) ? 1 : 0); + from_addr->node, hops, ticks, (hops > 15) ? 1 : 0); } else { /* rip request */ build_rip_buff(net); if (net == MAX_U32) break; @@ -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) @@ -699,12 +703,13 @@ 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=3, update routes */ -/* mode=4, resend to net */ -/* mode=5, force update routes */ +/* mode=0, standard broadcast */ +/* mode=1, first trie */ +/* 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) diff --git a/nwroute1.c b/nwroute1.c index f025964..78430be 100644 --- a/nwroute1.c +++ b/nwroute1.c @@ -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); diff --git a/nwserv.c b/nwserv.c index c29bad1..e82cb50 100644 --- a/nwserv.c +++ b/nwserv.c @@ -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; } @@ -635,10 +591,21 @@ static void handle_sap(int fd, static void response_ipx_diag(int fd, int ipx_pack_typ, ipxAddr_t *to_addr) { - IPX_DATA ipxdata; - DIAGRESP *dia = &ipxdata.diaresp; - uint8 *p = (uint8*) (dia+1); - int datalen = sizeof(DIAGRESP); /* erstmal */ + IPX_DATA ipxdata; + DIAGRESP *dia = &ipxdata.diaresp; + uint8 *p = (uint8*) (dia+1); + 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 */ - datalen++; - memcpy(p, my_server_adr.net, IPX_NET_SIZE); - p += IPX_NET_SIZE; - datalen += IPX_NET_SIZE; - memcpy(p, my_server_adr.node, IPX_NODE_SIZE); - datalen += IPX_NODE_SIZE; + /* --- Code by Valeri Bourak ----- */ + if (internal_net) { + (*net_count)++; + *p++ = 1; /* virtual board */ + datalen++; + 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--) { - t_unbind(sockfd[j]); - t_close(sockfd[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,15 +1111,25 @@ static void close_all(void) #ifdef LINUX # if INTERNAL_RIP_SAP #if 1 - if (!(ipx_flags&1)) { - for (j=0; jis_up==1) { /* only no auto interfaces */ - XDPRINTF((1, 0, "Close Device=%s, frame=%d", - nd->devname, nd->frame)); - exit_dev(nd->devname, nd->frame); + 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; jis_up==1) { /* only no auto interfaces */ + XDPRINTF((1, 0, "Close Device=%s, frame=%d", + nd->devname, nd->frame)); + exit_dev(nd->devname, nd->frame); + } } } + } else { + XDPRINTF((1, 0, "Not sending rip hangup, because ipxinuse")); } #endif exit_ipx(ipx_flags); @@ -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 } } diff --git a/nwserv.h b/nwserv.h index 5bdd2e4..6c45aa5 100644 --- a/nwserv.h +++ b/nwserv.h @@ -70,9 +70,9 @@ extern NW_NET_DEVICE **net_devices; #if INTERNAL_RIP_SAP # define RIP_SLOT (SAP_SLOT +1) +# define ROUTE_SLOT (RIP_SLOT +1) +# define DIAG_SLOT (ROUTE_SLOT +1) # if 0 -# define ROUTE_SLOT (RIP_SLOT +1) -# define DIAG_SLOT (ROUTE_SLOT +1) # define ECHO_SLOT (DIAG_SLOT +1) # define ERR_SLOT (ECHO_SLOT +1) # endif diff --git a/nwshare.c b/nwshare.c index b6774a2..34811ef 100644 --- a/nwshare.c +++ b/nwshare.c @@ -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,140 +25,688 @@ #include "unxfile.h" #include "nwshare.h" -#define MAX_SH_OP_DEV 20 +/* changed by: Ingmar Thiemann + * 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 ((!sh_mode) && fo==-1) { - XDPRINTF((1, 0, "Could not found share to remove")); + if (action==0 && !sd) { + XDPRINTF((1, 0, "Could not find share device to remove %s", tbuf)); 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 (!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; } - flockd.l_whence = SEEK_SET; - flockd.l_start = inode; - flockd.l_len = 1; - - if (!sh_mode) { - sod=&(sh_op_devs[fo]); - 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; + /* look for open inode */ + for (psi=&sd->first_inode; *psi; psi=&(*psi)->next) { + if ((*psi)->inode == inode) { + si = *psi; + break; } - } else { - if (fo == -1) { + } + + 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 (!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; - sod=&(sh_op_devs[fr]); 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); - 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(); - - if (sod->fd_r < 0) { - XDPRINTF((1, 0, "Cannot open sharefile=`%s`", buff)); - return(-1); - } - sod->dev = dev; } 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; + 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 ((!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)); - } else { - sod->in_use++; - } - } 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; + 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); } } + + flockd.l_whence = SEEK_SET; + flockd.l_start = inode; + flockd.l_len = 1; + + 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; + 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; + } + } + + flockd.l_type = F_UNLCK; + fcntl(sd->fd_sm, F_SETLK, &flockd); /* realise semaphor */ + + 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 ); + } + *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 + result = -1; + } else { + /* 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; + } + } + } + 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); +} + + + diff --git a/nwshare.h b/nwshare.h index 042d518..9c8e5ef 100644 --- a/nwshare.h +++ b/nwshare.h @@ -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 */ +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 diff --git a/nwvolume.c b/nwvolume.c index 27fa964..de63874 100644 --- a/nwvolume.c +++ b/nwvolume.c @@ -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 #include -#include + +#ifdef FREEBSD +# include +# include +#else +# include +#endif +#include #ifndef LINUX #include @@ -30,8 +37,12 @@ #include #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 */ + vol->options + |= (VOL_OPTION_TRUSTEES | VOL_OPTION_IGNUNXRIGHT); + break; + case 'O' : vol->options |= VOL_NAMESPACE_OS2; loaded_namespaces |= VOL_NAMESPACE_OS2; @@ -169,7 +233,7 @@ void nw_init_volumes(FILE *f) vol->umode_file = 0; if (founds > 3) { vol->umode_dir=octtoi(umode_dirstr); - if (founds > 4) + if (founds > 4) vol->umode_file=octtoi(umode_filestr); } used_nw_volumes++; @@ -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 = ""; - } 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])); + 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 { + 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, +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; @@ -262,27 +320,31 @@ void nw_setup_vol_opts(int act_gid, int act_uid, new_str(home_dir, unixname); 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 -#include #ifdef LINUX -# include +# ifndef QTAINSYS +# include +# else +# ifdef _GNU_SOURCE_ +# include +# endif +# include +# endif + # if defined(__alpha__) # include # include diff --git a/nwvolume.h b/nwvolume.h index 4f6142a..41f96ad 100644 --- a/nwvolume.h +++ b/nwvolume.h @@ -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,21 +58,34 @@ 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 */ -#define VOL_OPTION_DOWNSHIFT 0x0001 /* downshift */ -#define VOL_OPTION_IS_PIPE 0x0002 /* Volume contains pipes */ -#define VOL_OPTION_REMOUNT 0x0004 /* Volume can be remounted (cdroms) */ -#define VOL_OPTION_IS_HOME 0x0008 /* Volume is USERS HOME */ -#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_DOWNSHIFT 0x0001 /* downshift */ +#define VOL_OPTION_IS_PIPE 0x0002 /* Volume contains pipes */ +#define VOL_OPTION_REMOUNT 0x0004 /* Volume can be remounted (cdroms) */ +#define VOL_OPTION_IS_HOME 0x0008 /* Volume is USERS HOME */ +#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 -#define VOL_NAMESPACE_OS2 0x2000 -#define VOL_NAMESPACE_NFS 0x4000 +#define VOL_NAMESPACE_DOS 0x1000 +#define VOL_NAMESPACE_OS2 0x2000 +#define VOL_NAMESPACE_NFS 0x4000 /* stolen from GNU-fileutils */ /* Space usage statistics for a filesystem. Blocks are 512-byte. */ @@ -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, +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 diff --git a/tools.c b/tools.c index 1c478f3..50a6a47 100644 --- a/tools.c +++ b/tools.c @@ -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 #include +#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 */ +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){ - errorp(1, "xmalloc", "not enough core, need %d Bytes\n", size); - exit(1); - } - return(p); + 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; @@ -501,7 +562,7 @@ void init_tools(int module, int options) use_syslog=1; if (NWSERV == module) { - fprintf(stdout, "\n\nMars_nwe V%d.%02dpl%d started using %s.\n", + fprintf(stdout, "\n\nMars_nwe V%d.%02dpl%d started using %s.\n", _VERS_H_, _VERS_L_, _VERS_P_, FILENAME_NW_INI); fprintf(stdout, "If you have problems, please read mars_nwe/doc/BUGS !\n"); if (use_syslog==1) { @@ -608,7 +669,7 @@ int octtoi(char *buf) } if (*buf == 0 || 1 != sscanf(buf, "%o", &i)) i=0; - else if (m) + else if (m) i=-i; } return(i); @@ -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; - } - } - } - fclose(f); - } else { - XDPRINTF((3, 0, "find_station_match, cannot open '%s'", - station_fn)); - } + 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); } - 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) ); } diff --git a/tools.h b/tools.h index 147fe2b..49ee041 100644 --- a/tools.h +++ b/tools.h @@ -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_ */ diff --git a/tools.sh b/tools.sh new file mode 100755 index 0000000..5b24854 --- /dev/null +++ b/tools.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +yesno() +{ + echo "" + echo $@ + while true; do + echo "please answer with (Y)es or (N)o and ." + 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 diff --git a/trustee.c b/trustee.c new file mode 100644 index 0000000..c4348aa --- /dev/null +++ b/trustee.c @@ -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 +#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); +} + + diff --git a/trustee.h b/trustee.h new file mode 100644 index 0000000..067fe1c --- /dev/null +++ b/trustee.h @@ -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 diff --git a/unxfile.c b/unxfile.c index 2063d03..f822dea 100644 --- a/unxfile.c +++ b/unxfile.c @@ -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,10 +80,15 @@ 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); @@ -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 } diff --git a/unxfile.h b/unxfile.h index 1afd846..3e3aaed 100644 --- a/unxfile.h +++ b/unxfile.h @@ -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 diff --git a/unxlog.c b/unxlog.c index 941e45a..ea037dc 100644 --- a/unxlog.c +++ b/unxlog.c @@ -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 */ }