access_table() challenge - win a Samba t-shirt!
Michael Glauche
mg at plum.de
Sun Jan 16 21:44:07 GMT 2000
Andrew Tridgell wrote:
>
> I've just spent quite some time re-doing our deny mode code in
> Samba. We now pass (ie. match NT4) on all possible deny mode
> combinations.
> The challenge now is to recode access_table() so that it is as small
> as possible. Right now it is horrendous, but I suspect there is an
> underlying pattern that I have missed.
I give up .. :) at least with the manual "shuffle around" tactics.
I found some simpifications, but the code doesn't look MUCH better
now ... :( (code IS attached)
Anyone knows some Programs that can generate logics from a bit table ?
(We have some 10 bit input and 2 bit output ....)
(btw .. 10 bits = 3 old deny, 3 new deny, 2 old_mode ,2 additional)
IF you want that routine FAST, then we could use some logic arrary ...
:)
it is 1024 bytes small (2^10 = 1024 :)
BUT the code would be MUCH less readable then ...
After writing some rows of that 1024 byte table, I think some optimizion
potental lives in the ORDER of the enums :
that line : (old_deny == DENY_DOS || new_deny == DENY_DOS ||
old_deny == DENY_FCB || new_deny == DENY_FCB)
Give DENY_DOS = 000 (bit) and DENY_FCB = 100 (bit) then you can use :
((old_entry & 3) == 0) || (new_entry & 3) == 0)
regards,
Michael
--
Samba NT-Domain howto (in german)
http://www.sambahq.de
-------------- next part --------------
#include <stdio.h>
enum {DENY_DOS, DENY_READ, DENY_WRITE, DENY_FCB, DENY_ALL, DENY_NONE};
enum {AFAIL,AREAD,AWRITE,AALL};
enum {DOS_OPEN_RDONLY, DOS_OPEN_RDWR, DOS_OPEN_WRONLY};
#define BOOL int
/*******************************************************************
reproduce the share mode access table
this is horrendoously complex, and really can't be justified on any
rational grounds except that this is _exactly_ what NT does. See
the DENY1 and DENY2 tests in smbtorture for a comprehensive set of
test routines.
********************************************************************/
static int access_table1(int new_deny,int old_deny,int old_mode,
BOOL same_pid, BOOL isexe)
{
if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
if (same_pid) {
if (isexe && old_mode == DOS_OPEN_RDONLY &&
old_deny == DENY_DOS && new_deny == DENY_READ) {
return AFAIL;
}
if (!isexe && old_mode == DOS_OPEN_RDONLY &&
old_deny == DENY_DOS && new_deny == DENY_DOS) {
return AREAD;
}
if (new_deny == DENY_FCB && old_deny == DENY_DOS) {
if (isexe) return AFAIL;
if (old_mode == DOS_OPEN_RDONLY) return AFAIL;
return AALL;
}
if (old_mode == DOS_OPEN_RDONLY && old_deny == DENY_DOS) {
if (new_deny == DENY_FCB || new_deny == DENY_READ) {
if (isexe) return AREAD;
return AFAIL;
}
}
if (old_deny == DENY_FCB) {
if (new_deny == DENY_DOS || new_deny == DENY_FCB) return AALL;
return AFAIL;
}
}
if (old_deny == DENY_DOS || new_deny == DENY_DOS ||
old_deny == DENY_FCB || new_deny == DENY_FCB) {
if (isexe) {
if (old_deny == DENY_FCB || new_deny == DENY_FCB) {
return AFAIL;
}
if (old_deny == DENY_DOS) {
if (new_deny == DENY_READ &&
(old_mode == DOS_OPEN_RDONLY ||
old_mode == DOS_OPEN_RDWR)) {
return AFAIL;
}
if (new_deny == DENY_WRITE &&
(old_mode == DOS_OPEN_WRONLY ||
old_mode == DOS_OPEN_RDWR)) {
return AFAIL;
}
return AALL;
}
if (old_deny == DENY_NONE) return AALL;
if (old_deny == DENY_READ) return AWRITE;
if (old_deny == DENY_WRITE) return AREAD;
}
/* it isn't a exe, dll, sym or com file */
if (old_deny == new_deny && same_pid)
return(AALL);
if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL;
if (old_mode == DOS_OPEN_RDONLY) return(AREAD);
return(AFAIL);
}
switch (new_deny)
{
case DENY_WRITE:
if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD);
if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE);
if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL);
return(AFAIL);
case DENY_READ:
if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD);
if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE);
if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL);
return(AFAIL);
case DENY_NONE:
if (old_deny==DENY_WRITE) return(AREAD);
if (old_deny==DENY_READ) return(AWRITE);
if (old_deny==DENY_NONE) return(AALL);
return(AFAIL);
}
return(AFAIL);
}
static int access_table2(int new_deny,int old_deny,int old_mode,
BOOL same_pid, BOOL isexe)
{
if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
if (same_pid) {
if (old_deny == DENY_DOS) {
if (!isexe && old_mode == DOS_OPEN_RDONLY &&
new_deny == DENY_DOS) {
return AREAD;
}
if (new_deny == DENY_FCB) {
if (isexe) return AFAIL;
if (old_mode == DOS_OPEN_RDONLY) return AFAIL;
return AALL;
}
if (old_deny == new_deny)
return(AALL);
}
if (old_deny == DENY_FCB) {
if ((new_deny == DENY_DOS || new_deny == DENY_FCB) ) return AALL;
return AFAIL;
}
}
if (isexe) {
if (old_deny == DENY_DOS ) {
if (new_deny == DENY_WRITE && (old_mode == DOS_OPEN_WRONLY || old_mode == DOS_OPEN_RDWR)) {
return AFAIL;
}
if (new_deny == DENY_READ && (old_mode == DOS_OPEN_RDONLY || old_mode == DOS_OPEN_RDWR)) {
return AFAIL;
}
}
if (old_deny == DENY_FCB || new_deny == DENY_FCB) {
return AFAIL;
}
if (old_deny == DENY_DOS || new_deny == DENY_DOS ||
old_deny == DENY_FCB || new_deny == DENY_FCB) {
if (old_deny == DENY_DOS || old_deny == DENY_NONE) {
return AALL;
}
if (old_deny == DENY_READ) return AWRITE;
if (old_deny == DENY_WRITE) return AREAD;
}
}
if (old_deny == DENY_DOS || new_deny == DENY_DOS ||
old_deny == DENY_FCB || new_deny == DENY_FCB) {
/* it isn't a exe, dll, sym or com file */
if (old_deny == DENY_READ || new_deny == DENY_READ) return AFAIL;
if (old_mode == DOS_OPEN_RDONLY) return(AREAD);
return(AFAIL);
}
switch (new_deny)
{
case DENY_WRITE:
if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_RDONLY) return(AREAD);
if (old_deny==DENY_READ && old_mode==DOS_OPEN_RDONLY) return(AWRITE);
if (old_deny==DENY_NONE && old_mode==DOS_OPEN_RDONLY) return(AALL);
return(AFAIL);
case DENY_READ:
if (old_deny==DENY_WRITE && old_mode==DOS_OPEN_WRONLY) return(AREAD);
if (old_deny==DENY_READ && old_mode==DOS_OPEN_WRONLY) return(AWRITE);
if (old_deny==DENY_NONE && old_mode==DOS_OPEN_WRONLY) return(AALL);
return(AFAIL);
case DENY_NONE:
if (old_deny==DENY_WRITE) return(AREAD);
if (old_deny==DENY_READ) return(AWRITE);
if (old_deny==DENY_NONE) return(AALL);
return(AFAIL);
}
return(AFAIL);
}
main()
{
int od, nd, om, sp, ie;
for (od=DENY_DOS;od <= DENY_NONE; od++)
for (nd=DENY_DOS;nd <= DENY_NONE; nd++)
for (om=DOS_OPEN_RDONLY;om <= DOS_OPEN_WRONLY; om++)
for (sp=0; sp <= 1; sp++)
for (ie=0; ie <= 1; ie++) {
if (access_table1(nd, od, om, sp, ie) !=
access_table2(nd, od, om, sp, ie)) {
printf("failed\n");
exit(1);
}
}
return 0;
}
More information about the samba-technical
mailing list