Intial commit

This commit is contained in:
Mario Fetka
2024-05-27 16:13:40 +02:00
parent f8dc12b10a
commit d71d446104
2495 changed files with 539746 additions and 0 deletions

1
prospero/server/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Makefile

View File

@@ -0,0 +1,39 @@
-*-text-*-
This document describes the compatability features of the Version 5 server.
The version 5 server is also capable of responding to requests from
clients speaking version 1 of the Prospero Protocol. However, the
user should note the following:
1) The version 1 clients and server never fully implemented the
quoting mechanisms that were specified in the Prospero protocol
version 1 spec. So, if you use version 5 clients to create links to
files with spaces or newlines in their names, or have hostnames with
strange characters in their names, or have attributes with strange
characters in their names or values, the version 1 clients may not
interpret protocol messages about them correctly. There is no fix.
If you want to, you can add code to server/dirsrv_v1.c that keeps
messages about such objects from being sent; I have not taken the time
to do so.
2) Version 1 Attributes only had type ASCII. Version 5 attributes
have type SEQUENCE, and may contain multiple tokens. When speaking to
a version 1 protocol server, SEQUENCE attributes are returned with the
multiple tokens space-separated. Other types of attributes will be
ignored.
3) It would be best to just forget about using filters with version 1 protocol
clients speaking to a version 5 server. Filters have changed
radically in version 5, and I have not struggled to make them
backwards compatible with version 1 filters.
4) Access methods have changed radically from version 1 to version 5,
as has the syntax of external links. The ACCESS-METHOD attribute is
being appropriately munged for the occasion. So you're safe :).
5) The Prospero version 4 clients and server never fully implemented
the V1 protocol's EDIT-LINK-INFO and EDIT-OBJECT-INFO. This remains
true; you must use version 5 protocol to edit link and object attributes.
6) Version 1 protocol clients have no way of sending KERBEROS
authentication messages.

25
prospero/server/FILES Normal file
View File

@@ -0,0 +1,25 @@
COMPATABILITY
FILES
Makefile.dist
create_link.c
create_obj.c
cvt_v1_ltype.c
delete_link.c
dirsrv.c
dirsrv.h
dirsrv_v1.c
ed_link_info.c
ed_obj_info.c
edit_acl.c
forwarded.c
get_obj_info.c
list.c
list_acl.c
parameter.c
pstart.c
pw_edit.c
restart_srv.c
shadowcvt.c
shadowcvt.doc
update.c
version.c

243
prospero/server/Makefile.in Executable file
View File

@@ -0,0 +1,243 @@
SOURCEBASE=..
include $(SOURCEBASE)/Makefile.config
CFILES = \
cvt_v1_ltype.c \
create_link.c \
create_obj.c \
delete_link.c \
dirsrv.c \
dirsrv_v1.c \
edit_acl.c \
ed_link_info.c \
ed_obj_info.c \
get_obj_info.c \
forwarded.c \
list.c \
list_acl.c \
parameter.c \
pstart.c \
pw_edit.c \
restart_srv.c \
shadowcvt.c \
update.c \
version.c
OBJECTS = \
shadowcvt.o \
pstart.o \
pw_edit.o \
$(DIRSRV_OBJECTS)
DIRSRV_OBJECTS = \
cvt_v1_ltype.o \
create_link.o \
create_obj.o \
delete_link.o \
dirsrv.o \
dirsrv_v1.o \
edit_acl.o \
ed_link_info.o \
ed_obj_info.o \
get_obj_info.o \
forwarded.o \
list.o \
list_acl.o \
parameter.o \
restart_srv.o \
update.o \
version.o
SPECIAL_PROGS = dirsrv pstart
SPECIAL_OTHERTARGETS = pw_edit shadowcvt
# MORE_SERVER_PROGS is a subset of OTHERTARGETS that are compiled by default.
# Set in MAkefile.config
# pw_edit is the admin program to locally edit the server's P_PASSWORD
# database.
all: ${SPECIAL_PROGS} ${MORE_SERVER_PROGS}
dirsrv: $(DIRSRV_OBJECTS) ${SRV_LIBS_DEPENDENCIES}
${CC} ${CFLAGS} -o $@ $(DIRSRV_OBJECTS) $(SRV_LIBS)
pstart: pstart.o $(SRV_LIBS_DEPENDENCIES)
${CC} ${CFLAGS} -o $@ $@.o $(SRV_LIBS)
pw_edit: pw_edit.o ${SRV_LIBS_DEPENDENCIES}
${CC} ${CFLAGS} -o $@ $@.o $(SRV_LIBS)
shadowcvt: shadowcvt.o cvt_v1_ltype.o $(SRV_LIBS_DEPENDENCIES)
${CC} ${CFLAGS} -o $@ $@.o cvt_v1_ltype.o $(SRV_LIBS)
install:
-for i in ${SPECIAL_PROGS} ${MORE_SERVER_PROGS}; do \
${INSTALL} -c -m 755 -o ${OWNER} -g ${GROUP} $$i ${P_BINARIES}/$$i${GENERATIONSUFFIX}; \
${GENERATION} ${P_BINARIES}/$$i ; \
done
-chmod 6755 ${P_BINARIES}/pstart
# Dependencies
cvt_v1_ltype.o : ../include/pserver.h \
../include/pfs.h ../include/pfs_utils.h ../include/ardp.h \
../include/pfs_threads.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/implicit_fixes.h \
../include/pmachine.h \
../include/perrno.h
create_link.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h dirsrv.h
create_obj.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h dirsrv.h
delete_link.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/pparse.h \
../include/plog.h ../include/psrv.h ../include/perrno.h dirsrv.h
dirsrv.o : \
../include/posix_signal.h \
../include/ardp.h \
../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/pserver.h ../include/psite.h ../include/plog.h \
../include/pprot.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h \
../include/ppasswd.h dirsrv.h
dirsrv_v1.o : \
../include/posix_signal.h \
../include/pmachine.h ../include/pserver.h \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h \
../include/implicit_fixes.h \
../include/psrv.h ../include/pparse.h \
../include/plog.h ../include/pprot.h ../include/perrno.h \
dirsrv.h
edit_acl.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/psrv.h ../include/pparse.h \
../include/plog.h ../include/perrno.h dirsrv.h
ed_link_info.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h dirsrv.h
ed_obj_info.o : ../include/ardp.h \
../include/pfs_threads.h \
../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/perrno.h ../include/plog.h \
../include/pparse.h ../include/pprot.h ../include/psrv.h \
dirsrv.h
get_obj_info.o : \
../include/pmachine.h ../include/ardp.h ../include/pfs_threads.h \
../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h \
../include/implicit_fixes.h \
../include/pserver.h ../include/pparse.h \
../include/psrv.h ../include/plog.h ../include/pprot.h \
../include/perrno.h dirsrv.h
forwarded.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h dirsrv.h
list.o : \
../include/pmachine.h ../include/ardp.h ../include/pfs_threads.h \
../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h \
../include/implicit_fixes.h \
../include/pparse.h \
../include/pserver.h ../include/psrv.h ../include/plog.h ../include/pprot.h \
../include/perrno.h dirsrv.h
list_acl.o : ../include/ardp.h \
../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/perrno.h ../include/pprot.h \
dirsrv.h
parameter.o : ../include/ardp.h \
../include/pfs_threads.h \
../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/pserver.h ../include/plog.h \
../include/psrv.h ../include/pparse.h ../include/ppasswd.h \
dirsrv.h ../include/perrno.h
pstart.o : \
../include/pmachine.h \
../include/pserver.h \
../include/pfs.h ../include/pfs_utils.h ../include/ardp.h ../include/pfs_threads.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h ../include/implicit_fixes.h \
../include/pprot.h
pw_edit.o : \
../include/pfs.h ../include/pfs_utils.h ../include/ardp.h \
../include/pfs_threads.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h ../include/implicit_fixes.h \
../include/pmachine.h \
../include/pserver.h \
../include/posix_signal.h \
../include/ppasswd.h
restart_srv.o : \
../include/ardp.h ../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/pserver.h ../include/plog.h \
../include/psrv.h ../include/pparse.h dirsrv.h ../include/sockettime.h \
../include/posix_signal.h
shadowcvt.o : ../include/pfs.h \
../include/pfs_utils.h ../include/ardp.h \
../include/pfs_threads.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/implicit_fixes.h \
../include/pmachine.h \
../include/pserver.h ../include/pprot.h ../include/pparse.h
update.o : \
../include/ardp.h \
../include/pfs_threads.h ../include/pfs_utils.h \
../include/list_macros.h ../include/../lib/ardp/flocks.h \
../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/plog.h \
../include/perrno.h ../include/psrv.h ../include/pparse.h ../include/pprot.h \
dirsrv.h
version.o : ../include/ardp.h \
../include/pfs_threads.h \
../include/pfs_utils.h \
../include/list_macros.h \
../include/../lib/ardp/flocks.h ../include/pfs.h ../include/pmachine.h \
../include/implicit_fixes.h \
../include/pserver.h ../include/plog.h \
../include/pprot.h ../include/pparse.h ../include/psrv.h \
dirsrv.h

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
/* Seriously mutilated by swa@isi.edu, 9/21/92 */
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h> /* SOLARIS doesnt have strings.h */
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#include <pparse.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
int
create_link(RREQ req, char **commandp, char **next_wordp,
INPUT in, char client_dir[], int dir_magic_no)
{
VLINK clink; /* For stepping through links */
PATTRIB at; /* Attributes */
int tmp;
char t_linktype;
char t_fname[ARDP_PTXT_LEN_R];
char t_options[ARDP_PTXT_LEN_R];
VDIR_ST dir_st; /* Directory contents used ... */
VDIR dir = &dir_st; /* by individual lines */
int retval;
vdir_init(dir);
tmp = qsscanf(*next_wordp, "%'s %r", t_options, next_wordp);
/* Log and return a better message */
if(tmp < 2)
return error_reply(req, "Too few arguments: %'s", *commandp, 0);
/* Read link info. and attributes. */
retval =
in_link(in, *commandp, *next_wordp, 0, &clink,
(TOKEN *) NULL);
if (retval)
return error_reply(req, "%s", p_err_string, 0);
/* Do we need a better log message? */
plog(L_DIR_UPDATE, req,"CL %s %c %s %s %s %s %s %s", client_dir,
clink->linktype, clink->name, clink->target, clink->hosttype,
clink->host, clink->hsonametype,clink->hsoname,0);
/* The next two tests are repeated several places throughout the code.
Might be Nice if we made a function out of them. */
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED) {
dforwarded(req, client_dir, dir_magic_no, dir);
vlfree(clink);
return PSUCCESS;
}
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR, req,"Invalid directory name: %s", client_dir,0);
vlfree(clink);
RETURNPFAILURE;
}
/* If not authorized, say so */
if(!srv_check_acl(dir->dacl,NULL,req, "I",SCA_DIRECTORY,client_dir,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req, "Unauthorized CREATE-LINK: %s %s",client_dir,
t_fname, 0);
/* Free the directory links */
vlfree(clink);
vdir_freelinks(dir);
RETURNPFAILURE;
}
/* Make sure creator has all rights to link */
if(!srv_check_acl(dir->dacl,NULL,req, "alrmd",
SCA_DIRECTORY,client_dir,NULL))
srv_add_client_to_acl("alrmd",req,&(clink->acl),EACL_LINK);
retval = vl_insert(clink,dir,VLI_NOCONFLICT);
if((retval == VL_INSERT_ALREADY_THERE) ||
(retval == UL_INSERT_ALREADY_THERE)) {
creplyf(req,"FAILURE ALREADY-EXISTS %'s\n",clink->name);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
else if(retval == VL_INSERT_CONFLICT) {
creplyf(req,"FAILURE NAME-CONFLICT %'s\n",clink->name);
plog(L_DIR_ERR, req,"Conflicting link already exists: %'s %'s",
client_dir, clink->name,0);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
if(!retval) retval = dswdir(client_dir,dir);
/* if successful say so (need to clean this up) */
if(!retval)
reply(req,"SUCCESS\n");
else
creplyf(req,
"FAILURE SERVER-FAILED Unable to write server directory %s\n",
client_dir );
/* Free the directory links */
vdir_freelinks(dir);
return(retval);
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
/*
* Modified 6/4/93, swa: It now writes out the child directory first.
* It only writes out the changed parent directory if the child directory
* was successfully written. This means that if we have trouble writing the
* child directory, we don't end up with a parent directory containing
* a link to a nonexistent object.
*/
/*
* Modified 11/2/93, swa: Now allocates VIRTUAL subdirectories out of an
* object pool if the parent is not NONATIVE. This solves the previous buggy
* method of creating VIRTUAL subdirectories of real UNIX directories.
*/
ACL aclcopy(ACL acl);
static VLINK
gensym_child(VDIR dir, char *newdir_parent, char *child_linkname,
char **child_hsonamep);
/* This was create_directory */
int
create_object(RREQ req, char **commandp, char **next_wordp, INPUT in,
char client_dir[], int dir_magic_no)
{
AUTOSTAT_CHARPP(t_optionsp); /* options to command. */
AUTOSTAT_CHARPP(child_linknamep); /* link name in parent. */
AUTOSTAT_CHARPP(child_hsonamep); /* HSONAME for the child. */
VLINK clink; /* For the child directory. */
int tmp;
int lpriv; /* LPRIV option */
int retval;
VDIR_ST dir_st; /* Parent directory contents. */
VDIR dir = &dir_st;
VDIR_ST new_dir_st; /* Child directory contents. */
VDIR new_dir = &new_dir_st;
/* Now set object_pool in dirsrv.c */
/* still have to read the remainder of the attributes */
tmp = qsscanf(*next_wordp,"%'&s %'&s",
t_optionsp, child_linknamep);
/* Log and return a better message */
if(tmp < 2) {
creply(req,"ERROR too few arguments");
plog(L_DIR_PERR,req,"Too few arguments: %s",
*commandp, 0);
RETURNPFAILURE;
}
/* For now, VIRTUAL and DIRECTORY options must be specified */
if(!sindex(*t_optionsp, "VIRTUAL")
|| !sindex(*t_optionsp, "DIRECTORY")) {
creply(req,"ERROR only VIRTUAL directories implemented\n");
plog(L_DIR_PERR,req,"Tried to create non-VIRTUAL or
non-directory object: %'s",
*commandp, 0);
RETURNPFAILURE;
}
if(sindex(*t_optionsp,"LPRIV")) lpriv = 1;
else lpriv = 0;
plog(L_DIR_UPDATE,req,"%s", *commandp, 0);
vdir_init(dir);
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED)
return dforwarded(req, client_dir, dir_magic_no, dir);
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR,req,"Invalid directory name: %'s", client_dir,0);
RETURNPFAILURE;
}
/* If not authorized, say so */
if(!srv_check_acl(dir->dacl,NULL,req,"I",SCA_DIRECTORY,client_dir,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized CREATE-DIRECTORY: %s %s",client_dir,
*child_linknamep);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
clink = gensym_child(dir, client_dir, *child_linknamep, child_hsonamep);
if (!clink) {
creply(req, "FAILURE SERVER-FAILED Could not generate a unique \
hsoname for the new directory.\n");
vdir_freelinks(dir);
RETURNPFAILURE;
}
retval = vl_insert(clink,dir,VLI_NOCONFLICT);
if(retval == VL_INSERT_ALREADY_THERE) {
creplyf(req,"FAILURE ALREADY-EXISTS %'s\n",clink->name);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
else if(retval == VL_INSERT_CONFLICT) {
creplyf(req,"FAILURE NAME-CONFLICT %'s\n",clink->name);
plog(L_DIR_ERR,req,"Conflicting link already exists: %s %s",client_dir,
clink->name,0);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
/* Don't write out the parent yet! */
/* Initialize the new directory. The child will get a copy of the parent's
ACL. */
vdir_init(new_dir);
new_dir->inc_native = VDIN_NONATIVE;
/* Add creator to the ACL */
if(!lpriv || (!srv_check_acl(dir->dacl,NULL,req,"BIlr",
SCA_DIRECTORY,client_dir,NULL))) {
/* need to copy since EACL_ADD may change it */
new_dir->dacl = aclcopy(dir->dacl);
if(lpriv) srv_add_client_to_acl("AIlr",req,&(new_dir->dacl),
EACL_DIRECTORY);
else srv_add_client_to_acl("ALRWDE",req,&(new_dir->dacl),
EACL_DIRECTORY);
}
else {
new_dir->dacl = dir->dacl;
}
if(!retval) retval = dswdir(*child_hsonamep,new_dir);
/* Ok, now we can write out the parent. */
if(!retval) retval = dswdir(client_dir,dir);
/* Free the entries */
if (dir->dacl == new_dir->dacl) new_dir->dacl = NULL; /* don't free twice*/
vdir_freelinks(dir);
vdir_freelinks(new_dir);
/* if successful say so (need to clean this up) */
if(!retval) reply(req,"SUCCESS\n");
else creply(req,"FAILURE\n");
return retval;
}
/* Gensym a vlink for the child directory. */
static VLINK
gensym_child(VDIR dir, char *newdir_parent, char *child_linkname,
char **child_hsonamep)
{
VDIR_ST tmp_dir_st; /* scratch directory */
VDIR tmp_dir = &tmp_dir_st; /* scratch directory */
int retval; /* value returned by dsrdir() */
/* Allocate a link for the child directory. */
VLINK clink = vlalloc();
clink->name = stcopyr(child_linkname,clink->name);
clink->target = stcopyr("DIRECTORY",clink->target);
clink->host = stcopyr(hostwport,clink->host);
/* come up with an unused hsoname for the new directory. */
*child_hsonamep = qsprintf_stcopyr(*child_hsonamep, "%s/%s",
dir->inc_native == VDIN_NONATIVE ? newdir_parent : object_pool,
child_linkname);
/* Try first a name unadorned with a :# */
vdir_init(tmp_dir);
retval = dsrdir(*child_hsonamep, 0L, tmp_dir, (VLINK) NULL, 0);
if (retval == PSUCCESS) {
char *template = NULL;
int i;
template = qsprintf_stcopyr(template, "%s:%%d", *child_hsonamep);
i = 1;
for (;;) {
*child_hsonamep = qsprintf_stcopyr(*child_hsonamep, template, i);
vdir_freelinks(tmp_dir);
retval = dsrdir(*child_hsonamep, 0L, tmp_dir, (VLINK) NULL, 0);
if (retval != PSUCCESS)
/* Either *child_hsonamep now has an unused name or reading that
directory failed for some reason we can't do much about */
break;
++i;
}
}
vdir_freelinks(tmp_dir);
if (retval != DSRDIR_NOT_A_DIRECTORY) {
/* dsrdir() failed for some reason other than because *child_hsonamep was
unused. We can't do much about it here if it wasn't caught when
reading the parent. */
vlfree(clink);
return NULL;
}
clink->hsoname = stcopyr(*child_hsonamep, clink->hsoname);
return clink;
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <pserver.h>
#ifdef SERVER_SUPPORT_V1
#include <pfs.h>
#include <perrno.h>
/* cur_link->target is already set to l_type. Return PSUCCESS if this is OK.
*/
int
convert_v1_ltype(char l_type[], VLINK cur_link)
{
char *param;
PATTRIB amat; /* Access-method attribute. */
if (strequal(l_type, "SYM-LINK")) {
cur_link->target = stcopyr("SYMBOLIC", cur_link->target);
return PSUCCESS;
}
if (!strnequal(l_type, "EXTERNAL(", 9))
return PSUCCESS;
if (strequal(l_type, "EXTERNAL(AFTP,BINARY)"))
param = "BINARY";
else if (strequal(l_type, "EXTERNAL(AFTP,TEXT)"))
param = "TEXT";
else
RETURNPFAILURE;
cur_link->target = stcopyr("EXTERNAL", cur_link->target);
/* Ok, now set it. */
amat = atalloc();
if (!amat) out_of_memory();
amat->precedence = ATR_PREC_LINK;
amat->value.sequence = (TOKEN) NULL;
amat->nature = ATR_NATURE_FIELD;
amat->avtype = ATR_SEQUENCE;
amat->aname = stcopyr("ACCESS-METHOD", amat->aname);
amat->value.sequence = tkappend("AFTP", amat->value.sequence);
/* next 4 are null strings; they are all the same, by convention. */
amat->value.sequence = tkappend("", amat->value.sequence);
amat->value.sequence = tkappend("", amat->value.sequence);
amat->value.sequence = tkappend("", amat->value.sequence);
amat->value.sequence = tkappend("", amat->value.sequence);
amat->value.sequence = tkappend(param, amat->value.sequence);
APPEND_ITEM(amat, cur_link->lattrib);
return PSUCCESS;
}
#endif /* SERVER_SUPPORT_V1 */

View File

@@ -0,0 +1,143 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <plog.h>
#include <psrv.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
static void
srv_vl_delete(VDIR dir, VLINK vl);
int
delete_link(RREQ req, char *command, char *next_word, INPUT in,
char client_dir[], int dir_magic_no)
{
char t_name[ARDP_PTXT_LEN_R];
char t_options[ARDP_PTXT_LEN_R];
long t_magic_no = 0; /* 0 means none specified. */
int retval;
ACL wacl; /* Working access control list */
int tmp; /* return value from qsscanf() */
char *cp; /* dummy pointer */
VLINK vl = NULL; /* target link */
VDIR_ST dir_st; /* Directory contents used ... */
VDIR dir = &dir_st; /* by individual lines */
vdir_init(dir);
tmp = qsscanf(next_word,"%'s %'s %r", t_options, t_name, &cp);
/* Log and return a better message */
if (tmp < 0)
return error_reply(req, "Format error: %'s", command, 0);
if(tmp < 2)
return error_reply(req, "Too few arguments: %'s", command, 0);
if (tmp > 2)
return error_reply(req, "Too many arguments: %'s", command, 0);
if(retval = in_select(in, &t_magic_no))
return error_reply(req, "DELETE-LINK: %'s", p_err_string);
if (!strequal(t_options, ""))
return error_reply(req, "DELETE-LINK: options must be empty: %'s",
command);
/* Do we need a better log message */
plog(L_DIR_UPDATE,req,"RM %s %s ID REMOTE %ld",
client_dir,t_name,t_magic_no,0);
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED)
return dforwarded(req, client_dir, dir_magic_no, dir);
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR, req,"Invalid directory name: %s", client_dir,0);
RETURNPFAILURE;
}
/* Need to find the link so we can check its ACL */
for( vl = dir->links; vl; vl = vl->next) {
if(strequal(vl->name,t_name) && vl->linktype != '-')
if ((t_magic_no == 0) || (t_magic_no == vl->f_magic_no))
break;
}
if (!vl) {
for( vl = dir->ulinks; vl; vl = vl->next) {
if(strequal(vl->name,t_name))
if ((t_magic_no == 0) || (t_magic_no == vl->f_magic_no))
break;
}
}
if (!vl) {
creplyf(req, "FAILURE NOT-FOUND LINK %'s\n", t_name);
plog(L_DIR_ERR,req,"Link not found: %s %s", client_dir, t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
wacl = vl->acl;
/* If not authorized, say so */
if(!srv_check_acl(wacl, dir->dacl, req,"d",SCA_LINK,NULL,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized DELETE-LINK: %s %s",client_dir,
t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
if (vl->flags & VLINK_NATIVE) {
creplyf(req, "FAILURE SERVER-FAILED Deleting NATIVE links is not \
defined nor implemented. You can try instead either \
(a) manually deleting the link named %'s in the native UNIX directory %'s \
on the host %'s \
or (b) setting the link invisible: \
set_atr <linkname> LINK-TYPE -linkprec -replace -field I \
(see any version of the user''''s manual dated \
11/3/93 or later for a discussion of this).\n", t_name, client_dir, hostname);
plog(L_FAILURE, req, "Tried to DELETE-LINK on NATIVE link: %s %s",
client_dir, t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
srv_vl_delete(dir, vl);
retval = dswdir(client_dir,dir);
vdir_freelinks(dir);
if(!retval) {
reply(req,"SUCCESS\n");
} else {
creplyf(req, "FAILURE SERVER-FAILED Unable to write out modified directory %'s\n", client_dir);
}
return retval;
}
static void
srv_vl_delete(VDIR dir, VLINK vl)
{
if (vl->linktype == 'U') {
EXTRACT_ITEM(vl, dir->ulinks);
vlfree(vl);
#if 0
} else if (vl->flags & VLINK_NATIVE) {
vl->linktype = '-';
if (dir->inc_native == VDIN_ONLYREAL) dir->inc_native = VDIN_INCLREAL;
#endif
} else {
EXTRACT_ITEM(vl, dir->links);
vlfree(vl);
}
}

1797
prospero/server/dirsrv.c Normal file

File diff suppressed because it is too large Load Diff

190
prospero/server/dirsrv.h Normal file
View File

@@ -0,0 +1,190 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
/*
* CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H:
* include/pprot.h, server/dirsrv.h
* This appears to be an unpleasant interaction between GCC
* version 1.41 and the Ultrix version 4.2A system include files. The
* compiler complained about conflicting definitions of NULL in <sys/param.h>
* and <stddef.h>. The definitions are in fact the same, but with different
* spacing, which the ANSI standard says should be irrelevant.
* (Section 3.8.3, 'Macro Replacement' clearly states that:
* "An object currently defined as a macro without use of lparen (an
* object-like macro) may be reedefined by another #define preprocessing
* directive provided that the second definition is an object-like macro
* definition and the two replacement lists are identical."
* It also clearly states that, in considering whether the replacment lists
* are identical, "all white-space separations are considered identical"
* You can #define this if you encounter this bug. It will slightly slow
* down the compilation if this is left #defined, but not very much.
* I suggest you define it by modifying the definition of MACHDEF in the
* top-level MAKEFILE, since this gross kludge is necessary both in
* pprot.h and in pmachine.h.
*/
#if defined (NOTDEFINED)
#define CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#endif
#define MAX_VERSION 5 /* Highest version number supported */
#define MIN_VERSION 1 /* Lowest version number supported */
/* Commands */
#define UNKNOWN (-1) /* Unknown command. */
#define UNIMPLEMENTED 0 /* Unimplemented */
#define VERSION 1 /* Set or request protocol version number */
/* AUTHENTICATOR is the V1 form. */
#define AUTHENTICATOR 2 /* Provides authentication information */
#define AUTHENTICATE 2 /* Provides authentication information */
#define DIRECTORY 3 /* Set current working directory */
#define LIST 4 /* List directory links matching args */
#define GET_OBJECT_INFO 5 /* Requests information about a file */
#define EDIT_OBJECT_INFO 6 /* used to change file attributes */
#define CREATE_LINK 7 /* Adds a new link to a directory */
#define DELETE_LINK 8 /* Removes existing link from directory */
/* MODIFY_LINK is the V1 command. */
#define MODIFY_LINK 9 /* Changes information about link */
#define EDIT_LINK_INFO 9
#define CREATE_OBJECT 10 /* Creates new file and returns pointer */
#define TERMINATE 11 /* Requests that server terminate -V1only */
/* CREATE_DIRECTORY was a V1 command; obsolete in V5. */
#define CREATE_DIRECTORY 12 /* Create new directory and returns ptr */
#define UPDATE 13 /* Update link by chasing forwarding ptr */
#define STATUS 14 /* Return server status */
#define LIST_ACL 15 /* Return access control list */
/* MODIFY_ACL is the V1 command. */
#define MODIFY_ACL 16 /* Modify access control list */
#define EDIT_ACL 16 /* Modify access control list */
/* This is obsolete. */
#define PACKET 17 /* Multi packet request (not implemented) */
#define RESTART 18 /* Requests that server restart itself-V1only*/
#define ATOMIC 19 /* Not yet implemented. */
#define PARAMETER 20 /* Server specific parameter operations */
#define OBSOLETE 21 /* This command is obsolete. Give up. */
/* These are global variables which are used by the dirsrv code. They are
defined in "dirsrv.c." They are mostly used by the stats generator. */
extern char prog[];
extern int fault_count;
extern char last_request[ARDP_PTXT_LEN_R];
extern char *last_error;
extern char st_time_str[40];
extern int in_port;
extern char *portname;
extern int req_count; /* How many requests total? */
#ifdef SERVER_SUPPORT_V1
extern int v1_oldform_req_count; /* How many Old format V1
requests? */
extern int v1_req_count; /* How many V1 format requests */
extern int crdir_count;
#ifdef __STDC__
int convert_v1_ltype(char l_type[], VLINK cur_link);
#endif
#endif
extern int crlnk_count;
extern int crobj_count;
extern int dellnk_count;
extern int eoi_count;
extern int goi_count;
extern int list_count;
extern int lacl_count;
extern int eli_count;
extern int eacl_count;
extern int status_count;
extern int upddir_count;
extern int parameter_count;
#ifndef MAXPATHLEN
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#undef NULL
#endif /* #ifdef CONFLICT... */
#include <sys/param.h>
/* Needed for SCOUNIX which doesnt define this in MAXPATHLEN */
#ifndef MAXPATHLEN
#define MAXPATHLEN 1024
#endif
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#ifndef NULL
#include <stddef.h>
#endif /* #ifndef NULL */
#endif /* #ifdef CONFLICT... */
#endif /* #ifndef MAXPATHLEN */
/* These are shared data storage areas. */
extern char shadow[MAXPATHLEN];
extern char pfsdat[MAXPATHLEN];
extern char dirshadow[MAXPATHLEN];
extern char dircont[MAXPATHLEN];
extern char *object_pool;
#define OBJECT_POOL "objectpool" /* This will be a subdirectory of the pfsdat
area. Should this go into an include file?
Eventually, when we redesign the database
format. */
extern char root[MAXPATHLEN];
extern char aftpdir[MAXPATHLEN];
extern char afsdir[MAXPATHLEN];
extern char *db_prefix;
extern char hostname[MAXPATHLEN]; /* Server's host name */
extern char hostwport[MAXPATHLEN+30]; /* Host name w/ port if non-standard
*/
extern char *logfile_arg;
extern struct db_entry db_prefixes[];
extern int db_num_ents;
/* This function is used by dirsrv_v1() and dirsrv(). */
extern int check_handle(char *handle);
extern void log_server_stats(void);
/* These functions are used by the new modular dirsrv() */
extern int create_link(RREQ, char **, char **, INPUT in, char [], int);
extern int create_object(RREQ, char **, char **, INPUT in, char [], int);
extern int delete_link(RREQ, char *, char *, INPUT in, char [], int);
extern int dforwarded(RREQ, char [], int, VDIR);
extern int obforwarded(RREQ, char [], long, P_OBJECT);
extern int dirsrv_v1(RREQ req,char *command_next);
extern int dlinkforwarded(RREQ req, OUTPUT out, char client_dir[],
int dir_magic_no, VDIR dir, char *components);
extern int oblinkforwarded(RREQ req, OUTPUT out, char client_dir[],
int dir_magic_no, P_OBJECT dirob, char *components);
extern int edit_acl(RREQ, char **, char **, INPUT in, char *, int);
extern int edit_link_info(RREQ, char **, char **, INPUT in, char [], int);
/* renamed to avoid conflict with edit_object_info in the PFS library. */
extern int srv_edit_object_info(RREQ, char *command, char *next_word,
INPUT in);
extern int forwarded(RREQ, VLINK, VLINK, char objectname[]);
extern int get_object_info(RREQ, char *, char *, INPUT in);
extern int list(RREQ, char **, char **, INPUT in, char [], int);
extern int list_acl(RREQ req, char * command, char *next_word,
INPUT in, char client_dir[], int dir_magic_no);
extern int parameter(RREQ req, char *command, char *next_word);
extern void restart_server(int, char *);
extern int update(RREQ req, char *command, char *next_word, INPUT in,
char client_dir[], int dir_magic_no);
extern int version(RREQ, char *command, char *next_word);
/* dirsrv utilities. */
VLINK check_fwd();
#ifdef PFS_THREADS
extern p_th_mutex p_th_mutexP_PARAMETER_MOTD;
#endif

1135
prospero/server/dirsrv_v1.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,273 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#include <pparse.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
static int vl_delete_attributes(), vl_delete_all_attributes(),
equal_attribute_names_and_nature();
int
edit_link_info(RREQ req, char **commandp, char **next_wordp, INPUT in,
char client_dir[], int dir_magic_no)
{
VLINK clink; /* For stepping through links */
PATTRIB at; /* Attributes */
int tmp; /* Temporary returns from qsscanf() */
char t_mod_request[ARDP_PTXT_LEN_R];
enum {ADD, REPLACE, DELETE, DELETE_ALL} e_mod_request;
char t_name[ARDP_PTXT_LEN_R];
long n_magic_no = 0;
VDIR_ST dir_st; /* Directory contents used ... */
VDIR dir = &dir_st; /* by individual lines */
int retval;
vdir_init(dir);
if(qsscanf(*next_wordp, "%!!s %!!'s",
t_mod_request, sizeof t_mod_request, t_name, sizeof t_name) < 2)
return error_reply(req, "Malformed command: %'s", *commandp);
if(in_select(in, &n_magic_no))
return error_reply(req, "EDIT-LINK-INFO: %'s", p_err_string);
if (strequal(t_mod_request, "ADD"))
e_mod_request = ADD;
else if (strequal(t_mod_request, "DELETE"))
e_mod_request = DELETE;
else if (strequal(t_mod_request, "REPLACE"))
e_mod_request = REPLACE;
else if (strequal(t_mod_request, "DELETE-ALL"))
e_mod_request = DELETE_ALL;
else
return error_reply(req, "Malformed command: %'s", *commandp);
if(in_atrs(in, 0, &at))
return error_reply(req, "EDIT-LINK-INFO: Could not read attributes \
from request packet: %'s", p_err_string);
plog(L_DIR_UPDATE,req,"ELI %s %s %s",client_dir,t_name,t_mod_request,0);
/* XXX: The next 2 screens of code would make a nice routine called
"find_named_link". Modularize! */
/* Open the directory. */
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED) {
dforwarded(req, client_dir, dir_magic_no, dir);
return PSUCCESS;
}
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR, req, "Invalid directory name: %s", client_dir,0);
RETURNPFAILURE;
}
clink = dir->links;
while(clink) {
if(strcmp(clink->name,t_name) == 0 && clink->linktype != '-')
break;
clink = clink->next;
}
if(!clink) {
clink = dir->ulinks;
while(clink) {
if(strcmp(clink->name,t_name) == 0)
break;
clink = clink->next;
}
}
if(!clink) {
creplyf(req,"FAILURE NOT-FOUND LINK %'s\n",t_name);
plog(L_DIR_ERR,req,"Link not found: %s %s",client_dir, t_name,0);
vdir_freelinks(dir);
RETURNPFAILURE;
}
/* CLINK is now set to the link we want to modify. */
/* If not authorized, say so */
if(!srv_check_acl(clink->acl,dir->dacl,req,"m",SCA_LINK,NULL,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized EDIT-LINK-INFO: %s %s",client_dir,
clink->name,0);
vdir_freelinks(dir);
RETURNPFAILURE;
}
/* Now that we have the link, and permission to modify it, and the
attributes, let's go do the modification! */
switch(e_mod_request) {
/* The cases in this switch are ALL RESPONSIBLE FOR DOING THEIR OWN
ERROR REPORTING upon failure. */
case ADD:
/* XXX this isn't really an ADD operation, because we overwrite
attributes that can only have single instances, without
complaining. However, it will suffice, since it handles all legal
requests correctly. */
/* this reports errors in p_err_string */
retval = vl_add_atrs(at, clink);
if (retval) {
creplyf(req, "FAILURE BAD-VALUE %'s\n", p_err_string);
plog(L_DIR_ERR, req, "Bad Value for MODIFY-LINK ADD: %'s", p_err_string);
}
break;
case DELETE:
retval = vl_delete_attributes(req, at, clink);
atlfree(at);
break;
case DELETE_ALL:
retval = vl_delete_all_attributes(req, at, clink, TRUE);
atlfree(at);
break;
case REPLACE:
retval = vl_delete_all_attributes(req, at, clink, FALSE);
if (!retval) {
retval = vl_add_atrs(at, clink);
if (retval) {
creplyf(req, "FAILURE BAD-VALUE %'s\n", p_err_string);
plog(L_DIR_ERR, req, "Bad Value for MODIFY-LINK REPLACE: %'s",
p_err_string);
}
}
break;
default:
internal_error("reached default case");
}
if(!retval) {
retval = dswdir(client_dir,dir);
if(!retval)
reply(req,"SUCCESS\n");
else
creplyf(req,"FAILURE SERVER-FAILED EDIT-LINK-INFO Couldn''''t \
write the changes to %'s\n", client_dir);
}
vdir_freelinks(dir);
return retval;
}
/* This does NOT free the attributes to be matched in the ATS list.
It DOES free the attributes that were deleted. */
static
int
vl_delete_attributes(req, ats, vl)
RREQ req;
PATTRIB ats;
VLINK vl;
{
static int vl_delete_attribute();
while(ats) {
if(vl_delete_attribute(ats, vl)) {
creplyf(req,"FAILURE NOT-FOUND Could not DELETE attribute %'s; \
this instance not found", ats->aname);
plog(L_DIR_ERR,req, "Desired Instance of an attribute not found \
to delete: %s", ats->aname);
RETURNPFAILURE;
} else {
ats = ats->next;
}
}
return PSUCCESS;
}
static int
vl_delete_attribute(at, vl)
PATTRIB at;
VLINK vl;
{
int retval;
/* Filter is the only one we need to special-case right now. */
/* All of the others object attributes have exactly one instance, except
for ID. */
if (strequal(at->aname, "ID") && at->nature == ATR_NATURE_FIELD) {
retval = delete_matching_at(at, &(vl->oid), equal_attributes);
if (retval == PSUCCESS && strequal(at->value.sequence->token, "REMOTE")
&& length(at->value.sequence) == 2)
vl->f_magic_no = 0;
return retval;
} else if (strequal(at->aname, "FILTER")
&& at->nature == ATR_NATURE_FIELD) {
return delete_matching_fl(at->value.filter, &(vl->filters));
} else {
return delete_matching_at(at, &(vl->lattrib), equal_attributes);
}
}
static
int
vl_delete_all_attributes(req, at, vl, complain)
RREQ req;
PATTRIB at;
VLINK vl;
int complain; /* TRUE if we object to deleting indelible
or non-present attributes. FALSE if we
don't mind. XXX -- currently ignored. */
{
static int vl_delete_all_attribute();
PATTRIB ind;
for (ind = at; ind; ind = ind->next) {
while(vl_delete_all_attribute(ind, vl) == PSUCCESS)
;
}
return PSUCCESS;
}
/* If there's more than one instance of the attribute, we delete only one.
Must be called repeatedly in order to really delete all of them. */
static
int
vl_delete_all_attribute(at, vl)
PATTRIB at;
VLINK vl;
{
static int equal_attribute_names_and_nature(PATTRIB, PATTRIB);
if (strequal(at->aname, "ID") && at->nature == ATR_NATURE_FIELD) {
atlfree(vl->oid);
vl->oid = NULL;
vl->f_magic_no = 0;
} else if (strequal(at->aname, "FILTER")
&& at->nature == ATR_NATURE_FIELD) {
fllfree(vl->filters);
vl->filters = NULL;
} else {
return delete_matching_at(at, &(vl->lattrib),
equal_attribute_names_and_nature);
}
return(PSUCCESS);
}
static
int
equal_attribute_names_and_nature(at1, at2)
PATTRIB at1, at2;
{
return at1->nature == at2->nature && strequal(at1->aname,at2->aname);
}

View File

@@ -0,0 +1,255 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <ardp.h>
#include <pfs.h>
#include <perrno.h>
#include <plog.h>
#include <pparse.h>
#include <pprot.h>
#include <psrv.h>
#include "dirsrv.h"
static int pf_delete_attributes(), pf_delete_all_attributes(),
equal_attribute_names_and_nature();
static int pf_add_atrs();
int
srv_edit_object_info(RREQ req, char *command, char *next_word, INPUT in)
{
char t_mod_request[40];
AUTOSTAT_CHARPP(t_handlep);
long t_magic_no = 0; /* should be used. */
enum {ADD, REPLACE, DELETE, DELETE_ALL} e_mod_request;
int rsinfo_ret;
PFILE fi;
int retval = PSUCCESS; /* return value from modification functions. */
PATTRIB at;
char *dummy_cp;
/* First, parse the input. */
if (qsscanf(next_word, "%!!s %*s %&'s %r",
t_mod_request, sizeof t_mod_request,
&*t_handlep, &dummy_cp) != 2)
return error_reply(req, "Malformed command: %'s", command);
if (strequal(t_mod_request, "ADD"))
e_mod_request = ADD;
else if (strequal(t_mod_request, "DELETE"))
e_mod_request = DELETE;
else if (strequal(t_mod_request, "REPLACE"))
e_mod_request = REPLACE;
else if (strequal(t_mod_request, "DELETE-ALL"))
e_mod_request = DELETE_ALL;
else
return error_reply(req, "Malformed command: %'s", command);
if (in_select(in, &t_magic_no))
return error_reply(req, "EDIT-OBJECT-INFO: %'s", p_err_string);
if(in_atrs(in, 0, &at))
return error_reply(req, "EDIT-OBJECT-INFO: Could not read attributes \
from request packet: %'s", p_err_string);
if (!at)
return error_reply(req, "No attributes provided to EDIT-OBJECT-INFO.");
plog(L_DIR_UPDATE, req, "EOI %s %s", *t_handlep, t_mod_request, 0);
fi = pfalloc();
if (!fi) out_of_memory();
/* Second, get the attribute list from the file. */
rsinfo_ret = dsrfinfo(*t_handlep,t_magic_no,fi);
if(rsinfo_ret == DSRFINFO_FORWARDED) {
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* Current forwarding pointer */
fl = fi->forward; fi->forward = NULL;
fp = check_fwd(fl,*t_handlep, t_magic_no);
/* Free what we don't need */
pffree(fi);
/* Reply with FORWARDED message. */
forwarded(req, fl, fp, *t_handlep);
return PSUCCESS;
}
if (rsinfo_ret > 0) {
pffree(fi);
/* We claim it was not found; the logfile tells the true tale. */
creplyf(req, "FAILURE NOT-FOUND FILE %'s\n", *t_handlep);
RETURNPFAILURE;
}
/* Third: make the modifications. */
switch(e_mod_request) {
case ADD:
/* If not authorized, say so */
if(!srv_check_acl(fi->oacl,NULL,req,"i",SCA_OBJECT,*t_handlep,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized EDIT-OBJECT-INFO ADD: %s",*t_handlep);
pffree(fi);
RETURNPFAILURE;
}
/* Always returns SUCCESS */
/* XXX this isn't really an ADD operation, because we overwrite
attributes that can only have single instances, without
complaining. However, it will suffice for this Alpha release,
until a need for something better comes along. --swa */
retval = pf_add_atrs(at, fi);
break;
case DELETE:
/* If not authorized, say so */
if(!srv_check_acl(fi->oacl,NULL,req,"z",SCA_OBJECT,*t_handlep,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized EDIT-OBJECT-INFO DELETE: %s",*t_handlep);
pffree(fi);
RETURNPFAILURE;
}
/* does its own error reporting. */
retval = pf_delete_attributes(req, at, fi);
atlfree(at);
break;
case DELETE_ALL:
/* If not authorized, say so */
if(!srv_check_acl(fi->oacl,NULL,req,"z",SCA_OBJECT,*t_handlep,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized EDIT-OBJECT-INFO DELETE ALL: %s",*t_handlep);
pffree(fi);
RETURNPFAILURE;
}
/* Does its own error reporting. */
retval = pf_delete_all_attributes(req, at, fi, TRUE);
atlfree(at);
break;
case REPLACE:
/* If not authorized, say so */
if(!srv_check_acl(fi->oacl,NULL,req,"u",SCA_OBJECT,*t_handlep,NULL)) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized EDIT-OBJECT-INFO DELETE: %s",*t_handlep);
pffree(fi);
RETURNPFAILURE;
}
/* delete and add do their own error reporting. */
if(!(retval = pf_delete_all_attributes(req, at, fi, FALSE)))
retval = pf_add_atrs(at, fi);
else
atlfree(at);
break;
default:
internal_error("");
}
/*
/* Save the results, if it worked. */
if (!retval) {
retval = dswfinfo(*t_handlep, fi);
if(!retval)
reply(req,"SUCCESS\n");
else
creplyf(req,"FAILURE SERVER-FAILED EDIT-OBJECT-INFO Couldn''''t \
write the changes to %'s\n", *t_handlep);
}
pffree(fi);
return retval;
}
/* This does NOT free the attributes it deletes. */
static
int
pf_delete_attributes(req, ats, fi)
RREQ req;
PATTRIB ats;
PFILE fi;
{
static int pf_delete_attribute();
while(ats) {
if(pf_delete_attribute(ats, fi)) {
creplyf(req,
"FAILURE Could not DELETE attribute %'s; this instance \
not found\n", ats->aname);
RETURNPFAILURE;
} else {
ats = ats->next;
}
}
return PSUCCESS;
}
static int
pf_delete_attribute(at, fi)
PATTRIB at;
PFILE fi;
{
return delete_matching_at(at, &(fi->attributes), equal_attributes);
}
static
int
pf_delete_all_attributes(req, at, pf, complain)
RREQ req;
PATTRIB at;
PFILE pf;
int complain; /* TRUE if we object to deleting indelible
or non-present attributes. FALSE if we
don't mind. XXX -- currently ignored. */
{
static int pf_delete_all_attribute();
PATTRIB ind;
for (ind = at; ind; ind = ind->next) {
while(pf_delete_all_attribute(ind, pf) == PSUCCESS)
;
}
return PSUCCESS;
}
/* If there's more than one instance of the attribute, we delete only one.
Must be called repeatedly in order to really delete all of them. */
static
int
pf_delete_all_attribute(at, fi)
PATTRIB at;
PFILE fi;
{
static int equal_attribute_names_and_nature(PATTRIB, PATTRIB);
return delete_matching_at(at, &(fi->attributes),
equal_attribute_names_and_nature);
}
static
int
equal_attribute_names_and_nature(at1, at2)
PATTRIB at1, at2;
{
return at1->nature == at2->nature && strequal(at1->aname,at2->aname);
}
/* Merge the attributres in AT with the PFILE fi. We need this function
because eventually we'll support modification of PFILE attributes that are
not stored in the attributes member. This destructively modifies the
attributes being merged. */
static int
pf_add_atrs(PATTRIB at, PFILE fi)
{
while(at) {
PATTRIB next = at->next;
APPEND_ITEM(at, fi->attributes);
at = next;
}
return PSUCCESS;
}

277
prospero/server/edit_acl.c Normal file
View File

@@ -0,0 +1,277 @@
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/* Credits: originally by bcn@cs.washington.edu 1989 -- 1991 */
/* Severely mutilated by swa@isi.edu, 9/21/92. */
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <psrv.h>
#include <pparse.h>
#include <plog.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
extern char *acltypes[];
int
edit_acl(RREQ req, char **commandp, char **next_wordp, INPUT in,
char client_dir[], int dir_magic_no)
{
char t_name[ARDP_PTXT_LEN_R];
char t_options[ARDP_PTXT_LEN_R];
char *p_principals;
int retval;
int n_options;
char insrights[ARDP_PTXT_LEN_R];
ACL nacl; /* New ACL entry */
int tmp;
PFILE fi = NULL;
int rsinfo_ret;
VDIR_ST dir_st; /* Directory contents used ... */
VDIR dir = &dir_st; /* by individual lines */
VLINK clink; /* For stepping through links */
ACL wacl; /* Working access control list */
int aclchk; /* Cached ACL check */
long t_magic_no;
char *dummy_cp;
int i;
vdir_init(dir);
*t_name = '\0'; /* t_name is not sent for the DIRECTORY option.
(or, if it is sent, should be sent null).
OBJECT option not implemented. */
p_principals = NULL;
tmp = qsscanf(*next_wordp, "%'!!s %'!!s %r", t_options, sizeof t_options,
t_name, sizeof t_name, next_wordp);
/* XXX for now, we ignore the ID field. */
if (in_select(in, &t_magic_no))
return error_reply(req, "EDIT-ACL: %'s", p_err_string);
/* Log and return a better message */
if(tmp != 2) {
creply(req,"ERROR EDIT-ACL Wrong number of arguments\n");
plog(L_DIR_PERR,req,"Too few arguments: %s", *commandp);
RETURNPFAILURE;
}
/* Do we need a better log message? */
plog(L_DIR_UPDATE,req,"EA %s %s %s",client_dir,t_name,t_options);
if(in_acl(in, &nacl)) {
creplyf(req, "ERROR %'s\n", p_err_string);
return perrno;
}
/* XXX This is a temporary limitation, although I've left it in the
protocol. We can change it later, but this will get us going for now.
*/
if (!nacl || nacl->next)
return error_reply(req,
"EDIT-ACL must be followed by exactly 1 ACL line.");
n_options = 0;
/* Parse the options */
/* Doesn't do a whole lot of error checking. */
if(sindex(t_options,"NOSYSTEM")) n_options|=EACL_NOSYSTEM;
if(sindex(t_options,"NOSELF")) n_options|=EACL_NOSELF;
if(sindex(t_options,"DEFAULT")) n_options|=EACL_DEFAULT;
if(sindex(t_options,"SET")) n_options |= EACL_SET;
if(sindex(t_options,"INSERT")) n_options|=EACL_INSERT;
if(sindex(t_options,"DELETE")) n_options|=EACL_DELETE;
if(sindex(t_options,"ADD")) n_options|=EACL_ADD;
if(sindex(t_options,"CREATE")) n_options|=EACL_CREATE;
if(sindex(t_options,"DESTROY")) n_options|=EACL_DESTROY;
if(sindex(t_options,"SUBTRACT")) n_options|=EACL_SUBTRACT;
if(sindex(t_options,"LINK")) n_options|=EACL_LINK;
if(sindex(t_options,"DIRECTORY")) n_options|=EACL_DIRECTORY;
if(sindex(t_options,"OBJECT")) n_options|=EACL_OBJECT;
if(sindex(t_options,"INCLUDE")) n_options|=EACL_INCLUDE;
if(sindex(t_options,"NAMED")) n_options|=EACL_NAMED;
if(!((n_options&EACL_OTYPE)^EACL_OBJECT)) {
fi = pfalloc();
if (!fi) out_of_memory();
retval = dsrfinfo(t_name,0,fi);
if(retval == DSRFINFO_FORWARDED) {
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* Current forwarding pointer */
fl = fi->forward; fi->forward = NULL;
fp = check_fwd(fl,t_name,0);
/* Free what we don't need */
pffree(fi); fi = NULL;
/* Got to location to return forwarded error */
forwarded(req, fl, fp, t_name);
return PSUCCESS;
}
wacl = fi->oacl;
}
else {
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED) {
return dforwarded(req, client_dir, dir_magic_no, dir);
}
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR, req, "Invalid directory name: %s", client_dir);
RETURNPFAILURE;
}
wacl = dir->dacl;
}
if(!((n_options&EACL_OTYPE)^EACL_LINK)) {
/* Need to find the link so we can change its ACL */
clink = dir->links;
while(clink) {
if(strcmp(clink->name,t_name) == 0 && clink->linktype != '-')
break;
clink = clink->next;
}
if(!clink) {
clink = dir->ulinks;
while(clink) {
if(strcmp(clink->name,t_name) == 0)
break;
clink = clink->next;
}
}
if(!clink) {
creplyf(req,"FAILURE NOT-FOUND LINK %'s\n",t_name);
plog(L_DIR_ERR,req,"Link not found: %s %s",client_dir,t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
if (clink->linktype == 'N') {
creplyf(req, "FAILURE SERVER-FAILED Modifying NATIVE links is not \
implemented. Reset this directory''''s INCLUDE-NATIVE attribute to \
NONATIVE and retry the operation.");
plog(L_FAILURE, req, "Tried to EDIT-ACL on NATIVE link: %s %s",
client_dir, t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
if(clink->acl) wacl = clink->acl;
/* Check and update link ACL */
aclchk = srv_check_acl(clink->acl,dir->dacl,req,"a",SCA_LINK,NULL,NULL);
if(!aclchk && nacl->rights && *(nacl->rights) &&
(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT) ||
!((n_options&EACL_OP)^EACL_SUBTRACT) ||
!((n_options&EACL_OP)^EACL_DELETE))) {
if(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT))
*insrights = ']';
else *insrights = '[';
strcpy(insrights+1,nacl->rights);
aclchk = srv_check_acl(clink->acl,dir->dacl,req,insrights,SCA_LINK,NULL,NULL);
/* Don't use this to upgrade [ to a */
if(aclchk) n_options |= EACL_NOSELF;
}
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,
"Unauthorized EDIT-ACL: %s %s",client_dir,t_name);
vdir_freelinks(dir);
RETURNPFAILURE;
}
retval = change_acl(&(clink->acl),nacl,req,n_options,dir->dacl);
/* if native and successful, native no more */
if (!retval && (clink->linktype == 'N'))
clink->linktype = 'L';
}
else if(!((n_options&EACL_OTYPE)^EACL_DIRECTORY)) {
/* Check and update directory ACL */
aclchk = srv_check_acl(dir->dacl,NULL,req,"A",SCA_DIRECTORY,
client_dir,NULL);
if(!aclchk && nacl->rights && *(nacl->rights) &&
(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT) ||
!((n_options&EACL_OP)^EACL_SUBTRACT) ||
!((n_options&EACL_OP)^EACL_DELETE))) {
if(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT))
*insrights = '>';
else *insrights = '<';
strcpy(insrights+1,nacl->rights);
aclchk = srv_check_acl(dir->dacl,NULL,req,insrights,SCA_DIRECTORY,
client_dir,NULL);
/* Don't use this to upgrade < to a */
if(aclchk) n_options |= EACL_NOSELF;
}
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR, req, "Unauthorized EDIT-ACL: %s %s",
client_dir,t_name);
/* Free the directory links */
vdir_freelinks(dir);
RETURNPFAILURE;
}
retval = change_acl(&(dir->dacl),nacl,req,n_options,dir->dacl);
}
else if(!((n_options&EACL_OTYPE)^EACL_OBJECT)) {
/* Check and update directory ACL */
aclchk = srv_check_acl(fi->oacl,NULL,req,"A",SCA_OBJECT,t_name,NULL);
if(!aclchk && nacl->rights && *(nacl->rights) &&
(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT) ||
!((n_options&EACL_OP)^EACL_SUBTRACT) ||
!((n_options&EACL_OP)^EACL_DELETE))) {
if(!((n_options&EACL_OP)^EACL_ADD) ||
!((n_options&EACL_OP)^EACL_INSERT))
*insrights = '>';
else *insrights = '<';
strcpy(insrights+1,nacl->rights);
aclchk = srv_check_acl(fi->oacl,NULL,req,insrights,
SCA_OBJECT,t_name,NULL);
/* Don't use this to upgrade < to a */
if(aclchk) n_options |= EACL_NOSELF;
}
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR, req, "Unauthorized EDIT-ACL: %s",
t_name);
/* Free the directory links */
pffree(fi); fi = NULL;
RETURNPFAILURE;
}
retval = change_acl(&(fi->oacl),nacl,req,n_options,fi->oacl);
}
else {
creply(req,"ERROR invalid or unimplemented option\n");
plog(L_DIR_PERR,req,"Invalid option: %s",*commandp);
vdir_freelinks(dir);
RETURNPFAILURE;
}
/* if unsuccessfull say so (need to clean this up) */
if(retval) creply(req,"FAILURE NOT-FOUND ACL\n");
else { /* Otherwise write the directory and indicate success */
if(!((n_options&EACL_OTYPE)^EACL_OBJECT)) {
retval = dswfinfo(t_name, fi);
}
else {
retval = dswdir(client_dir,dir);
}
if(retval) creply(req,"FAILURE\n");
else replyf(req,"SUCCESS\n",0);
}
vdir_freelinks(dir);
return(retval); /* successfully completed. */
}

149
prospero/server/forwarded.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#include <perrno.h>
#include <pmachine.h>
#include "dirsrv.h"
int
forwarded(RREQ req,
VLINK fl, /* List of forwarding pointers,
including: */
VLINK fp, /* The current forwarding ptr. */
char objectname[]) /* object being forwarde */
{
int retval;
if(fp) {
replyf(req,"FORWARDED %s %'s %s %'s %ld",
fp->hosttype,fp->host,fp->hsonametype,fp->hsoname,
fp->version, 0);
if (fp->dest_exp) {
char *cp = NULL;
replyf(req, " DEST-EXP %s\n",
cp = p_timetoasn_stcopyr(fp->dest_exp, cp));
stfree(cp);
} else
reply(req, "\n");
if (fp->f_magic_no > 0)
replyf(req, "ID REMOTE %ld\n", fp->f_magic_no,0);
retval = PSUCCESS;
} else {
creplyf(req,"FAILURE SERVER-FAILED the object %'s is marked as \
forwarded, but no forwarding pointer was found for it.\n", objectname);
retval = PFAILURE;
}
vllfree(fl);
return retval;
}
/* Forwarded directories. */
int
dforwarded(req, client_dir, dir_magic_no, dir)
RREQ req;
char client_dir[];
int dir_magic_no;
VDIR dir;
{
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* The current forwarding ptr. */
fl = dir->f_info->forward; dir->f_info->forward = NULL;
fp = check_fwd(fl,client_dir,dir_magic_no);
/* Free what we don't need */
vdir_freelinks(dir);
return forwarded(req, fl, fp, client_dir);
}
int
obforwarded(RREQ req, char client_dir[], long dir_magic_no, P_OBJECT dirob)
{
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* The current forwarding ptr. */
fl = dirob->forward; dirob->forward = NULL;
fp = check_fwd(fl,client_dir,dir_magic_no);
return forwarded(req, fl, fp, client_dir);
}
/* Like dforwarded, but reply with a LINK line (to be followed by a REMCOMP
line by the caller). */
int
dlinkforwarded(RREQ req, OUTPUT out, char client_dir[], int dir_magic_no,
VDIR dir, char *components)
{
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* The current forwarding ptr. */
int retval; /* value to return */
fl = dir->f_info->forward; dir->f_info->forward = NULL;
fp = check_fwd(fl,client_dir,dir_magic_no);
/* Free what we don't need */
vdir_freelinks(dir);
if(fp) {
fp->name = stcopyr("", fp->name);
fp->target = stcopyr("DIRECTORY", fp->target);
fp->linktype = 'L';
qoprintf(out, "LINK ");
out_link(out, fp, 0, (TOKEN) NULL);
retval = PSUCCESS;
} else {
creplyf(req,"FAILURE SERVER-FAILED the object %'s is marked as \
forwarded, but no forwarding pointer was found for it.\n", client_dir);
retval = PFAILURE;
}
vllfree(fl);
return retval;
}
/* Like dforwarded, but reply with a LINK line (to be followed by a REMCOMP
line by the caller). */
int
oblinkforwarded(RREQ req, OUTPUT out, char client_dir[], int dir_magic_no,
P_OBJECT dirob, char *components)
{
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* The current forwarding ptr. */
int retval; /* value to return */
fl = dirob->forward; dirob->forward = NULL;
fp = check_fwd(fl,client_dir,dir_magic_no);
if(fp) {
fp->name = stcopyr("", fp->name);
fp->target = stcopyr("DIRECTORY", fp->target);
fp->linktype = 'L';
qoprintf(out, "LINK ");
out_link(out, fp, 0, (TOKEN) NULL);
retval = PSUCCESS;
} else {
creplyf(req,"FAILURE SERVER-FAILED the object %'s is marked as \
forwarded, but no forwarding pointer was found for it.\n", client_dir);
retval = PFAILURE;
}
vllfree(fl);
return retval;
}

View File

@@ -0,0 +1,363 @@
/* Author: bcn@isi.edu */
/* Updated & modified by swa@isi.edu */
/* Updated: swa@ISI.EDU, 5/15/94: to change ways attribute names are parsed and
way dsrobject() is called. */
/*
* Copyright (c) 1991-1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
#include <netdb.h>
#include <sgtty.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <pmachine.h>
#include <ardp.h>
#include <pserver.h>
#include <pfs.h>
#include <pparse.h>
#include <psrv.h>
#include <plog.h>
#include <pprot.h>
#include <perrno.h>
#include "dirsrv.h"
#define REALLY_NEW_FIELD
#define RETURN(rv) { retval = (rv); goto cleanup ; }
int
get_object_info(RREQ req, char *command, char *next_word, INPUT in)
{
VLINK check_fwd();
int tmp;
optdecl;
AUTOSTAT_CHARPP(t_requestedp); /* attributes requested (unparsed form) */
AUTOSTAT_CHARPP(t_ntypep); /* handle type */
AUTOSTAT_CHARPP(t_fnamep); /* obj handle */
long t_version = 0; /* Object version */
long t_num = 0; /* Magic #. */
VLINK clink = NULL; /* Must be freed */
int item_count = 0; /* Count of returned items */
P_OBJECT ob = NULL; /* Must be freed on exit */
int rsinfo_ret; /* Ret Val from dsrfinfo */
int all = 0; /* List all attributes? */
int fp_anyway = 0;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
int retval; /* Value we are returning */
struct dsrobject_list_options listopts_st;
dsrobject_list_options_init(&listopts_st); /* Initialize this first; then
we can safely cleanup at the
end without worrying about
encountering a wild pointer.
*/
set_client_addr(req->peer_addr.s_addr);
reqtoout(req, out);
/* still have to read the remainder of the attributes */
tmp = qsscanf(next_word,"%'&s %'&s %'&s %d %r",
t_requestedp,t_ntypep,t_fnamep, &t_version, &next_word);
/* Log and return a better message */
if(tmp != 3 && tmp != 4) {
creply(req,"ERROR wrong number of arguments\n");
plog(L_DIR_PERR,req,"Wrong # of arguments: %s", command, 0);
RETURN(PFAILURE);
}
if(in_select(in, &t_num))
return error_reply(req, "GET-OBJECT-INFO %'s", p_err_string);
/* Do we need a better log message */
plog(L_DIR_REQUEST, req, "GOI %s %s", *t_requestedp,*t_fnamep,0);
if(check_handle(*t_fnamep) == FALSE) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR, req,"Invalid object name: %s",*t_fnamep,0);
RETURN(PFAILURE);
}
/* Parse *t_requestedp, the list of requested attributes. */
#ifdef DSROBJECT_LIST_OPTIONS_REQUESTED_ATTRS_BACK_COMPATIBILITY
/* If any contents to t_requestedp, then also set requested_attrs. This
will be cleaned up at the end. */
if (**t_requestedp)
listopts_st.requested_attrs =
qsprintf_stcopyr(NULL, "+%s+", *t_requestedp);
#endif /* DSROBJECT_LIST_OPTIONS_REQUESTED_ATTRS_BACK_COMPATIBILITY */
p__parse_requested_attrs(*t_requestedp, &(listopts_st.req_obj_ats) );
clink = vlalloc();
ob = oballoc();
clink->hsonametype = stcopyr(*t_ntypep,clink->hsonametype);
clink->hsoname = stcopyr(*t_fnamep,clink->hsoname);
clink->f_magic_no = t_num;
clink->version = t_version;
rsinfo_ret = dsrobject(req, clink->hsonametype, clink->hsoname,
clink->version, clink->f_magic_no, 0,
&listopts_st, ob);
#ifdef DIRECTORYCACHING
if (rsinfo_ret)
dsrobject_fail++;
#endif
/* If not authorized, say so. If able to read the file, but not */
/* attributes, then return ACCESS-METHOD and don't complain */
if((!srv_check_acl(ob->acl,NULL,req,"g",SCA_OBJECT,clink->hsoname,NULL)) &&
(!srv_check_acl(ob->acl,NULL,req,"G",SCA_OBJECT,clink->hsoname,NULL))) {
plog(L_AUTH_ERR,req,"Unauthorized GET-OBJECT-INFO: %s", clink->hsoname);
creply(req,"FAILURE NOT-AUTHORIZED\n");
RETURN(PFAILURE);
}
#ifndef SERVER_DO_NOT_SUPPORT_FORWARDING
/* Handle FORWARDING-POINTER as a special case. */
if(was_attribute_requested("FORWARDING-POINTER", &listopts_st.req_obj_ats)) {
if(rsinfo_ret == DSRFINFO_FORWARDED) {
VLINK fl; /* List of forwarding pointers. */
if(fl = check_fwd(ob->forward,clink->hsoname,
clink->f_magic_no)) {
replyf(req,"ATTRIBUTE OBJECT INTRINSIC FORWARDING-POINTER LINK\
L FP %'s %s %'s %s %'s %d %d\n",
clink->name,
fl->hosttype, fl->host,
fl->hsonametype, fl->hsoname,
fl->version,fl->f_magic_no,0);
item_count++;
}
} else if((clink->f_magic_no == 0) && (ob->magic_no != 0)) {
replyf(req,"ATTRIBUTE OBJECT INTRINSIC FORWARDING-POINTER LINK L \
FP %'s %s %s %s %'s %d %d\n",
clink->name,
clink->hosttype, hostwport,
clink->hsonametype, clink->hsoname,
clink->version,ob->magic_no,0);
item_count++;
}
} else if(rsinfo_ret == DSRFINFO_FORWARDED) {
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* Current forwarding pointer */
fl = ob->forward; ob->forward = NULL;
fp = check_fwd(fl,clink->hsoname,clink->f_magic_no);
/* Return forwarded message. */
forwarded(req, fl, fp, clink->hsoname);
RETURN(PSUCCESS);
}
#endif /* SERVER_DO_NOT_SUPPORT_FORWARDING */
/* Here we must check the file info, look for matching */
/* attributes and return them if authorized. */
/* Returning the ACCESS-METHOD attribute has special authorizations
attached to it. */
if(rsinfo_ret <= 0) {
/* Check whether to return just the ACCESS-METHOD attribute, or whether
to return all of them. */
int return_non_amat = srv_check_acl(ob->acl,NULL,req,"g",SCA_OBJECT,
clink->hsoname,NULL);
PATTRIB ca;
/* Change: 5/16/94: ob->attributes is now only set for attributes that
were specifically requested. */
for (ca = ob->attributes; ca; ca = ca->next) {
/* Check permissions */
if (return_non_amat || strequal(ca->aname, "ACCESS-METHOD")) {
out_atr(out, ca, 0);
item_count++;
}
}
} else if (rsinfo_ret == DIRSRV_NOT_FOUND) {
creply(req,"FAILURE NOT-FOUND\n");
RETURN(PFAILURE);
} else {
creplyf(req,"FAILURE SERVER-FAILED %s%s%s\n", p_err_text[rsinfo_ret],
*p_err_string? " " : "", p_err_string);
RETURN( PFAILURE);
}
/* If none match, say so */
if(!item_count)
reply(req,"NONE-FOUND\n");
RETURN(PSUCCESS);
cleanup: /* used by RETURN() */
#ifdef DSROBJECT_LIST_OPTIONS_REQUESTED_ATTRS_BACK_COMPATIBILITY
/* This, if set, is allocated by stcopyr(), so should be freed. */
stfree((char *) listopts_st.requested_attrs);
listopts_st.requested_attrs = NULL;
#endif /* DSROBJECT_LIST_OPTIONS_REQUESTED_ATTRS_BACK_COMPATIBILITY */
/* Free up the objects. */
tklfree(listopts_st.req_obj_ats.specific);
if(ob)
obfree(ob);
if(clink)
vlfree(clink);
return(retval);
}
/* I add this function here since it is used by get_obj_info().
Also used by list(), in server/list.c. Perhaps I should make it a library
function. --swa, 5/15/94 */
/* UNPARSED is an unparsed +-separated list of the requested attributes. The
list is not expected to be preceded and followed by a + sign. If it is,
then we will get attributes with empty names, which will not do anything
useful. (Prospero does not normally use the empty-named attribute, although
it also does not discriminate against it.) The attribute names will not
contain + signs. */
/* PARSED is that list in requested_attributes form. */
/* We assume that PARSED is initialized to NULL values. You should call
init_requested_attributes() on PARSED before invoking
p__parse_requested_attrs(). */
/* This way of specifying attributes will go away in a later revision of the
protocol. */
void
p__parse_requested_attrs(const char *unparsed,
struct requested_attributes *parsed)
{
for (;;) {
int tmp; /* tmp. return value from qsscanf(). Doesn't
need to be initialized here; set below. */
char *thisatstr = NULL; /* attribute name being parsed. */
TOKEN thisattoken ; /* processed form of above. Doesn't need to
be initialized; set below. */
#if 1
/* This will not allow the empty string as an attribute name; by way of
compensation, it will consider it unset.
*/
/* This version strips off any leading pluses (suppresses them). then
it pulls in a sequence of one or more non-plus characters as an
attribute name. Then it saves the rest of the string for another
feeding. */
tmp = qsscanf(unparsed, "%*(+)%&[^+]%r", &thisatstr, &unparsed);
#else
tmp = qsscanf(unparsed, "%&(^+)+%r", &thisatstr, &unparsed);
#endif
if (tmp < 1)
break; /* done */
assert(tmp == 2); /* assumption of this code. */
/* Now do a dispatch based upon the value of thisatstr. If this is a
symbolic attribute name (#ALL or #INTERESTING; others will be
recognized later), set the matching
flag. The only symbolic names currently used by the clients we
provide are #ALL and "ALL" (typo in pre-5/15/94 versions of ALS.C,
wasn't recognized by older servers, so no reason to support it now.)
--swa */
/* We deliberately insert 'thisatstr' into the list, so that
'#INTERESTING' will always match a literal '#INTERESTING', etc. */
if (strequal(thisatstr, "#ALL")) {
parsed->all = 1;
} else if (strequal(thisatstr, "#INTERESTING")) {
parsed->interesting = 1;
} else if (strequal(thisatstr, "#OBJECT")
|| strequal(thisatstr, "#FIELD")
|| strequal(thisatstr, "#APPLICATION")) {
/* This test catches other possible symbolic attribute names that
are specified in the protocol but not currently used. It used
to be performed in get_object_info(). */
parsed->all = 1;
}
/* Done with dispatch. */
/* This fragment of 4 lines is used in at least 2 places in Prospero;
probably more. */
thisattoken = tkalloc(NULL);
thisattoken->token = thisatstr;
thisatstr = NULL; /* flush it. */
APPEND_ITEM(thisattoken, parsed->specific);
/* Added this item to the list. */
}
/* Done; PARSED has now been set appropriately. This function returns no
status, since it will always succeed. */
}
/* Dispatch table used below: */
const static struct {
char *name;
int interesting:1; /* matches #INTERESTING. Note that until
#INTERESTING is better defined, interesting
is implemented as equivalent to #ALL in the
code in was_attribute_requested(), below. */
int minus:1; /* not returned to an #ALL */
int plus:1; /* always returned. */
} attribute_class_table[] = {
/* name INT - + */
{"CONTENTS", 0, 1, 0},
/* FORWARDING-POINTER is a special case; if it wasn't explicitly requested
but it is nevertheless present, we will return a FORWARDED message
instead of returning any attributes whatsoever. */
/* This is a change: should #ALL and #INTERESTING also match
FORWARDING-POINTER? They currently do*/
/* {"FORWARDING-POINTER", 0, 1, 0}, */
{"OBJECT-INTERPRETATION", 1, 0, 0},
{"QUERY-METHOD", 1, 0, 0},
/* Currently no other magic attributes. But there will be soon. */
};
/* Question: should we go to the trouble of getting the attribute named ATNAME?
ATNAME is the attribute we're wondering whether to return.
This tests PARSED. We use an internal dispatch table (Currently defined
right here, will later be more configurable) with the following rules:
INTERESTING only matches attributes with 'interesting' set.
MINUS, if set, means that the attribute is not returned to a "#ALL". PLUS
means the attribute is always returned.
Returns: non-zero if should return, zero if shouldn't */
int
was_attribute_requested(char *atname, struct requested_attributes *parsed)
{
int i;
int matches_all = 1;
int matches_interesting = 1;
int always_matches = 0;
for (i = 0; i < sizeof attribute_class_table / sizeof attribute_class_table[0];
++i) {
if(strequal(atname, attribute_class_table[i].name)) {
/* INTERESTING same as ALL for now. */
matches_interesting = !attribute_class_table[i].minus;
matches_all = !attribute_class_table[i].minus;
always_matches = attribute_class_table[i].plus;
break; /* don't need to look at the rest of the table.
*/
}
}
/* Done scanning the attribute_class_table. We might be able to decide
just based on that information. */
if (always_matches)
return 1;
/* Now look at PARSED */
/* First, the obvious classes */
if (matches_interesting && parsed->interesting)
return 1;
if (matches_all && parsed->all)
return 1;
/* Now check if this attribute was explicitly requested. */
if (member(atname, parsed->specific))
return 1;
/* No match based on this data. We might still match in special-case code
in our caller. For instance, LIST ... COMPONENTS always returns the
ACCESS-METHOD attribute for EXTERNAL links. */
return 0;
}

642
prospero/server/list.c Normal file
View File

@@ -0,0 +1,642 @@
/*
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1989 modified 1989-1992
* Modified by swa 3Q/92 V5 support, modularize, quoting, multiple names
* Modified by bcn 1/20/93 support multiple database prefixes
*/
#include <usc-license.h>
#define SERVER_SEND_NEW_MCOMP
#define REALLY_NEW_FIELD
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <pmachine.h>
#include <ardp.h>
#include <pfs.h>
#include <pparse.h>
#include <pserver.h>
#include <psrv.h>
#include <plog.h>
#include <pprot.h>
#include <perrno.h>
#include "dirsrv.h"
TOKEN p__tokenize_midstyle_mcomp(char *nextname);
/* Uncomment this for debugging and demonstration purposes. */
/* Leave it enabled for now, since it won't hurt anything. */
#define SERVER_PREDEFINED_IDENTITY_FILTER
#ifdef SERVER_PREDEFINED_IDENTITY_FILTER
static identity_filter(P_OBJECT dir, TOKEN args);
#endif
static int list_name(RREQ req, char *command, char arg_client_dir[],
int dir_magic_no, TOKEN components, int verify_dir,
int localexp, int non_object_attrib_fl, int alllinks, FILTER filters);
#ifdef ARCHIE
extern int archie_supported_version;
#endif
int list(RREQ req, char **commandp, char **next_wordp, INPUT in,
char client_dir[], int dir_magic_no)
{
/* Flags */
int non_object_attrib_fl; /* Send back atribues in list */
int localexp; /* OK to exp ul for remcomp */
int verify_dir; /* Only verifying the directory */
int filterfl = 0; /* specified the filter flag. */
FILTER filters = NULL; /* filters to apply */
optdecl;
int tmp;
AUTOSTAT_CHARPP(t_optionsp);
char *nextname; /* Next name to be resolved. */
int retval; /* Value returned by list_name. */
long dummy_magic_no; /* XXX currently ignored; shouldn't be. */
CHECK_MEM();
nextname = NULL;
/* Assume we can freely overwrite the buffer. */
tmp = qsscanf(*next_wordp, "%'&s COMPONENTS %r",
&*t_optionsp, &nextname);
if (tmp < 0)
interr_buffer_full();
if (in_select(in, &dummy_magic_no))
return error_reply(req, "LIST: %'s", p_err_string);
/* At this point, *t_optionsp is a '+'-separated list of options and nextname
should point to a space-separated list of names. */
CHECK_MEM();
/* Parse the options. */
optstart(*t_optionsp);
verify_dir = opttest("VERIFY") ? 1 : 0;
/* If EXPAND specified, remeber that fact */
CHECK_MEM();
if (opttest("EXPAND") || opttest("LEXPAND"))
localexp = 2;
else
localexp = 0;
if (opttest("ATTRIBUTES"))
non_object_attrib_fl = DSRD_ATTRIBUTES;
else
non_object_attrib_fl = 0;
CHECK_MEM();
if (opttest("FILTER")) {
/* leave commandp set the way it was, since we need it to report errors. */
char *line, *next_word;
filterfl = 1;
if (localexp)
return error_reply(req, "FILTER flag cannot be specified with \
LEXPAND or EXPAND flags: %'s\n", *commandp);
CHECK_MEM();
while (in_nextline(in) && strnequal(in_nextline(in), "FILTER", 6)) {
FILTER cur_fil;
if (in_line(in, &line, &next_word)) {
fllfree(filters);
RETURNPFAILURE; /* error reporting done by in_line() */
}
CHECK_MEM();
if (in_filter(in, line, next_word, 0, &cur_fil)) {
fllfree(filters);
return error_reply(req, "Could not parse a filter: %'s",
p_err_string, 0);
}
CHECK_MEM();
if (cur_fil->execution_location != FIL_SERVER || cur_fil->link
|| (cur_fil->type != FIL_DIRECTORY
&& cur_fil->type != FIL_HIERARCHY)
|| cur_fil->pre_or_post != FIL_PRE) {
fllfree(filters);
flfree(cur_fil);
return error_reply(req, "All filters to be applied at the\
server must have an execution location of SERVER and be PRE-expansion and be\
DIRECTORY or HIERARCHY filters and be PREDEFINED. This one\
does not meet those criteria: %'s", line);
}
APPEND_ITEM(cur_fil, filters);
/* Checking for whether this filter is defined on this server occurs
in list_name(), when we dispatch to the particular filter. */
}
CHECK_MEM();
if (!filters)
return error_reply(req, "LIST had FILTER option specified, but no \
filters were given.");
} else {
filterfl = 0;
}
CHECK_MEM();
plog(L_DIR_REQUEST, req, "L%s %s %s",
(verify_dir ? "V" : " "), client_dir, (nextname ? nextname : "*"));
/* Specifying no component is exactly equivalent to specifying '*' */
{
int listall_flag = 0;
TOKEN comps;
#ifdef DONT_ACCEPT_OLD_MCOMP
/* No clients left that transmit old styles, so guaranteed not to need
to adapt to both. */
if (nextname) comps = qtokenize(nextname);
#else /* There are some old-style clients. (accept both styles; transmit
old or new). */
if (nextname) comps = p__tokenize_midstyle_mcomp(nextname);
#endif
else {
listall_flag = 1;
/* COMPS shouldn't ever be looked at when listall flag is passed,
but it is. */
comps = tkalloc("*");
}
VLDEBUGBEGIN;
retval = list_name(req, *commandp, client_dir, dir_magic_no, comps, verify_dir,
localexp, non_object_attrib_fl, listall_flag, filters);
VLDEBUGEND;
tklfree(comps);
}
fllfree(filters);
return retval;
}
static int
list_process_filters_err_reply(RREQ req, P_OBJECT ob, FILTER filters);
static int
list_expand_local_ulinks(RREQ req, P_OBJECT ob);
static int
list_name(RREQ req, char *command, char arg_client_dir[], int dir_magic_no,
TOKEN remcomp, int verify_dir,
int localexp, int non_object_attrib_fl, int alllinks, FILTER filters)
{
char *thiscomp; /* component being worked on */
AUTOSTAT_CHARPP(client_dirp); /* Current directory. We make this a
temporary, because it is modified by
list_name. */
int item_count = 0; /* Count of returned items */
FILTER cfil; /* For iterating through filters. */
VLINK clink; /* For stepping through links */
VLINK crep; /* For stepping through replicas */
long dir_version = 0; /* Directory version nbr-currently ignored */
AUTOSTAT_CHARPP(dir_typep); /* Type of dir name (Currently, the only
supported value is ASCII) */
P_OBJECT ob = oballoc(); /* allocate an object to read into. */
P_OBJECT lastob = NULL; /* last object used. */
int retval; /* Return value from subfunctions */
int laclchkl; /* Cached ACL check */
int daclchkl; /* Cached ACL check */
int laclchkr; /* Cached ACL check */
int daclchkr; /* Cached ACL check */
PATTRIB ca; /* Current Attribute */
OUTPUT_ST out_st;
OUTPUT out = &out_st;
int orig_localexp = localexp; /* don't change this cached copy. */
struct dsrobject_list_options listopts;
reqtoout(req, out);
*client_dirp = stcopyr(arg_client_dir, *client_dirp);
*dir_typep = stcopyr("ASCII", *dir_typep); /* XXX must generalize this. */
list_start:
/* list_start always is entered with a clean directory. */
thiscomp = remcomp->token;
remcomp = remcomp->next;
/* THISCOMP refers to a single name-component. REMCOMP may refer to
additional components of a multiple-component name that should be
resolved. */
/* If only expanding last component, clear the flag */
if (localexp == 1)
localexp = 0;
/* If remaining components, expand union links for this component only */
if (remcomp && !localexp)
localexp = 1;
p_clear_errors();
dsrobject_list_options_init(&listopts);
listopts.thiscompp = &thiscomp;
listopts.remcompp = &remcomp;
listopts.requested_attrs = "#INTERESTING";
listopts.req_link_ats.interesting = 1; /* just request INTERESTING. */
listopts.filters = filters;
/* dsrobject() might expand multiple components. */
VLDEBUGBEGIN;
retval = dsrobject(req, *dir_typep, *client_dirp, dir_version, dir_magic_no,
verify_dir? DRO_VERIFY_DIR : 0, &listopts, ob);
VLDEBUGOB(ob);
VLDEBUGEND;
#ifdef DIRECTORYCACHING
if (retval) dsrobject_fail++;
#endif
if (retval == DSRFINFO_FORWARDED) {
/* We are NOT in the process of expanding a union link, since if we
were, the above test would have caught it. */
if (lastob) { /* if exploring a subcomponent */
/* XXX We should update the local link to point to the new location
too */
if (verify_dir) {
reply(req, "NONE-FOUND\n");
if (lastob) obfree(lastob);
if (ob) obfree(ob);
return PSUCCESS;
}
retval = oblinkforwarded(req, out, *client_dirp, dir_magic_no, ob,
thiscomp);
if (retval) {
if (lastob) obfree(lastob);
obfree(ob);
return retval;
}
if (remcomp) {
#ifdef SERVER_SEND_NEW_MCOMP
replyf(req, "UNRESOLVED");
out_sequence(out, remcomp);
#else
TOKEN acp;
replyf(req, "UNRESOLVED %'s", remcomp->token);
for (acp = remcomp->next; acp; acp = acp->next)
replyf(req, "/%'s", acp->token);
reply(req, "\n");
#endif
}
} else {
retval = obforwarded(req, *client_dirp, dir_magic_no, ob);
if (lastob) obfree(lastob);
obfree(ob);
return retval;
}
if (lastob) obfree(lastob);
obfree(ob);
return PSUCCESS;
}
/* Even if we were exploring a subcomponent, still cool to return these
error messages. */
/* If not a directory, say so */
if (retval == DIRSRV_NOT_FOUND ||
retval == PSUCCESS && !(ob->flags & P_OBJECT_DIRECTORY)) {
creply(req, "FAILURE NOT-A-DIRECTORY\n");
if (lastob) obfree(lastob);
obfree(ob);
RETURNPFAILURE;
}
/* If not authorized, say so */
if (retval == DIRSRV_NOT_AUTHORIZED) {
if (*p_err_string)
creplyf(req, "FAILURE NOT-AUTHORIZED %'s\n", p_err_string, 0);
else
creply(req, "FAILURE NOT-AUTHORIZED\n");
if (lastob) obfree(lastob);
obfree(ob);
RETURNPFAILURE;
}
/* If too many links in response, say so */
if (retval == DIRSRV_TOO_MANY) {
if (*p_err_string)
creplyf(req, "FAILURE TOO-MANY %'s\n", p_err_string, 0);
else
creply(req, "FAILURE TOO-MANY\n");
if (lastob) obfree(lastob);
obfree(ob);
RETURNPFAILURE;
}
/* If some other failure, say so */
if (retval) {
if (*p_err_string)
creplyf(req, "FAILURE SERVER-FAILED %'s %'s\n", p_err_text[retval],
p_err_string);
else
creplyf(req, "FAILURE SERVER-FAILED %'s\n", p_err_text[retval]);
if (lastob) obfree(lastob);
obfree(ob);
return (retval);
}
if (*p_warn_string) {
replyf(req, "WARNING MESSAGE %'s\n", p_warn_string);
*p_warn_string = '\0';
}
list_expand_local_ulinks(req, ob); /* pass request just to give the security context. */
/* Cache the default answers for ACL checks */
daclchkl = srv_check_acl(ob->acl, ob->acl, req, "l",
SCA_LINKDIR,*client_dirp,NULL);
daclchkr = srv_check_acl(ob->acl, ob->acl, req, "r",
SCA_LINKDIR,*client_dirp,NULL);
if (retval = list_process_filters_err_reply(req, ob, filters)) {
if (lastob) obfree(lastob);
obfree(ob);
return retval;
}
/* When we reach this point, there's no going back.
Just spit out the links and clean up. */
/* Here we must send back the links, excluding those that do */
/* not match the component name. For each link, we must also */
/* send back any replicas or links with conflicting names */
for (clink = ob->links; clink; clink = clink->next) {
crep = clink;
while (crep) {
/* Check individual ACL only if necessary */
if (crep->acl) {
laclchkl = srv_check_acl(crep->acl, ob->acl, req, "l",
SCA_LINK,NULL,NULL);
laclchkr = srv_check_acl(crep->acl, ob->acl, req, "r",
SCA_LINK,NULL,NULL);
} else {
laclchkl = daclchkl;
laclchkr = daclchkr;
}
if (!verify_dir && wcmatch(crep->name, thiscomp) &&
crep->linktype != '-' &&
(laclchkl || (laclchkr &&
(strcmp(crep->name, thiscomp) == 0)))) {
if (laclchkr) {
if (remcomp && strequal(crep->host, hostwport) &&
!(crep->filters) && !item_count) {
/* If components remain on this host */
/* And links haven't already been returned */
/* don't reply, but continue searching */
/* Here's where we start to resolve additional
components */
/* Set the directory for the next component */
/* At this point, clink contains the link for the next
directory, and the directory itself is still filled
in. We should save away the old directory
information in case we need to backtrack */
dir_version = clink->version;
dir_magic_no = clink->f_magic_no;
*dir_typep = stcopyr(clink->hsonametype, *dir_typep);
*client_dirp = stcopyr(clink->hsoname, *client_dirp);
if (lastob) obfree(lastob);
lastob = ob;
#if 0
/* Save last remcomp in case this lookup fails. This
is actually not currently being used. */
last_remcomp = remcomp;
#endif
ob = oballoc();
goto list_start;
}
qoprintf(out, "LINK ");
out_link(out, crep, 0, (TOKEN) NULL);
/* If link attributes are to be returned, do so */
/* For now, only link attributes returned */
/* XXX this is not all of what we want. We need to be able to
explicitly read the values of attributes such as DEST-EXP
and ID. But this is all we need to get Gopher running. */
if (non_object_attrib_fl) {
for (ca = crep->lattrib; ca; ca = ca->next) {
/* For now return all attributes. To be done: */
/* return only those requested */
if (1) {
out_atr(out, ca, 0);
}
}
} else {
/* No attribute flag specified. Return ACCESS-METHOD for
EXTERNAL links anyway. */
if (strequal(crep->target, "EXTERNAL"))
for (ca = crep->lattrib; ca; ca = ca->next)
if (strequal(ca->aname, "ACCESS-METHOD"))
out_atr(out, ca, 0);
}
/* If there are any filters, send them back too */
if (laclchkr) {
for (cfil = crep->filters; cfil; cfil = cfil->next) {
#ifdef REALLY_NEW_FIELD
qoprintf(out,
"ATTRIBUTE LINK FIELD FILTER FILTER ");
#else
qoprintf(out, "ATTRIBUTE LINK FIELD FILTER ");
#endif
out_filter(out, cfil, 0);
}
}
} else {
/* If list access but no read access, just acknowledge that
the link exists. */
replyf(req, "LINK L NULL %s NULL NULL NULL NULL 0\n",
crep->name);
}
item_count++;
}
/* Replicas are linked through next, not replicas */
/* But the primary link is linked to the replica */
/* list through replicas */
if (crep == clink)
crep = crep->replicas;
else
crep = crep->next;
}
}
/* here we must send back the unexpanded union links */
for(clink = ob->ulinks; clink && !verify_dir; clink = clink->next) {
/* Neither return nor expand links that have been successfully expanded
or that are dummies.
*/
if (clink->expanded == ULINK_PLACEHOLDER || clink->expanded == TRUE)
continue; /* never return or process this link. */
/* If the user explicitly requested that union links be expanded
(original localexp == 2) or if we ended up expanding these links
as part of the intermediate stages of processing a multi-
component name (localexp == 1) then the user doesn't care about
seeing union links for the current directory, nor does he or she
care about getting two union links that agree in hsoname and
host but disagree in their NAME field. However, if the user
wants to see all the contents of the current directory, then
they very much do care to see conflicting union links. */
if (clink->expanded == ULINK_DONT_EXPAND && orig_localexp)
continue;
/* Return any readable union links. */
if (srv_check_acl(clink->acl, ob->acl,
req, "r", SCA_LINK,NULL,NULL)) {
/* Once one union link is going to be returned, don't do any more
expanding. */
localexp = 0;
qoprintf(out, "LINK ");
out_link(out, clink, 0, (TOKEN) NULL);
/* If link attributes are to be returned, do so */
/* For now, only link attributes returned */
/* XXX this is not all of what we want. We need to be able to
explicitly read the values of attributes such as DEST-EXP
and ID. But this is all we need to get Gopher running. */
if (non_object_attrib_fl) {
for (ca = clink->lattrib; ca; ca = ca->next) {
/* For now return all attributes. To be done: */
/* return only those requested */
if (1) {
out_atr(out, ca, 0);
}
}
}
item_count++;
/* if there are any filters */
for (cfil = clink->filters; cfil; cfil = cfil->next) {
#ifdef REALLY_NEW_FIELD
qoprintf(out, "ATTRIBUTE LINK FIELD FILTER FILTER ");
#else
qoprintf(out, "ATTRIBUTE LINK FIELD FILTER ");
#endif
out_filter(out, cfil, 1);
}
}
}
/* If none match, say so */
if (!item_count)
reply(req, "NONE-FOUND\n");
/* Otherwise, if components remain say so */
else if (remcomp) {
#ifdef SERVER_SEND_NEW_MCOMP
replyf(req, "UNRESOLVED");
out_sequence(out, remcomp);
#else
TOKEN acp;
replyf(req, "UNRESOLVED %'s", remcomp->token);
for (acp = remcomp->next; acp; acp = acp->next)
replyf(req, "/%'s", acp->token);
reply(req, "\n");
#endif
}
/* Free the directory links */
if (lastob) obfree(lastob);
if (ob) obfree(ob);
return PSUCCESS;
}
static int
list_process_filters_err_reply(RREQ req, P_OBJECT ob, FILTER filters)
{
#ifdef ARCHIE
int already_applied_ar_domain = 0;
int already_applied_ar_pathcomp = 0;
#endif
/* PUT IN CODE HERE TO PROCESS PREDEFINED SERVER FILTERS */
for (; filters; filters = filters->next) {
if (filters->pre_or_post == FIL_ALREADY) {
#ifdef ARCHIE
if (strequal(filters->name, "AR_DOMAIN"))
++already_applied_ar_domain;
if (strequal(filters->name, "AR_PATHCOMP"))
++already_applied_ar_pathcomp;
#endif
continue;
}
if (filters->pre_or_post == FIL_FAILED) {
if (filters->errmesg) {
creplyf(req, "FAILURE FILTER-APPLICATION Applying the %'s \
PREDEFINED SERVER filter yielded an error: %'s\n",
filters->name, filters->errmesg);
} else {
creplyf(req, "FAILURE FILTER-APPLICATION Applying the %'s \
PREDEFINED SERVER filter yielded an error.\n",
filters->name);
}
}
#ifdef SERVER_PREDEFINED_IDENTITY_FILTER
/* this only exists for debugging and demonstration purposes. */
if (strequal(filters->name, "IDENTITY")) {
int retval = identity_filter(ob, filters->args);
if (retval) {
creplyf(req, "FAILURE FILTER-APPLICATION Applying the %'s \
PREDEFINED SERVER filter yielded an error: %'s\n",
filters->name, p_err_string);
return retval;
}
} else
#endif
#ifdef ARCHIE
/* If specified should have been applied as part of query.
If it were applied as part of the archie database query, it would
have been taken care of by the test above against FIL_ALREADY. */
if (strequal(filters->name, "AR_DOMAIN") ||
strequal(filters->name, "AR_PATHCOMP")) {
if (!already_applied_ar_domain || !already_applied_ar_pathcomp)
creplyf(req, "FAILURE NOT-FOUND FILTER version %d archie servers do not support the PREDEFINED SERVER filter named %'s.\n",
archie_supported_version, filters->name);
else
creplyf(req, "FAILURE FILTER-APPLICATION The filter %'s \
cannot be applied more than once.\n", filters->name);
RETURNPFAILURE;
} else
#endif /* ARCHIE */
{
/* Filter not found. */
creplyf(req, "FAILURE NOT-FOUND FILTER This server does not \
support the PREDEFINED SERVER filter named %'s.\n", filters->name);
RETURNPFAILURE;
}
}
return PSUCCESS; /* all were succesfully processed */
}
#ifdef SERVER_PREDEFINED_IDENTITY_FILTER
/* Return PSUCCESS on success; failure indication otherwise & set p_err_string.
This is a sample filter to demonstrate how one writes such things. It's
also useful for debugging filters. */
static int identity_filter(P_OBJECT dirob, TOKEN args)
{
dirob->inc_native = VDIN_MUNGED;
return PSUCCESS;
}
#endif /* SERVER_PREDEFINED_IDENTITY_FILTER */
/* Pass the request just to give the security context.
*/
/* Expand all local union links where we have 'r' permission on the link in the
context of this directory. */
static int
list_expand_local_ulinks(RREQ req, P_OBJECT ob)
{
ob->inc_native = VDIN_MUNGED;
#if 0
/* Make sure that ob has enough information in it (or enough info. is
passed down to expand_local_ulinks) so that we can be sure to keep track
of what the starting directory for expansion was. */
if (localexp) {
/* Add a placeholder union link to indicate that the current directory
is already being expanded, so don't expand it again. This handles
recursive union links (a fairly frequent case) more efficiently than
not including this check. */
uexp = vlalloc();
assert(uexp);
uexp->host = stcopyr(hostwport, uexp->host);
uexp->hsoname = stcopyr(*client_dirp, uexp->hsoname);
uexp->f_magic_no = dir_magic_no;
uexp->expanded = ULINK_PLACEHOLDER;
dir->ulinks = uexp;
}
#endif
return PSUCCESS;
}

261
prospero/server/list_acl.c Normal file
View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 1992, 1993,1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>.
*/
#include <usc-license.h>
/* Originally written by BCN */
/* Seriously mutilated by swa@isi.edu, 9/29/92 -- 9/30/92 */
/* Memory leak fixed, swa, 3/31/94, thanks to mitra for noticing a potential
problem. */
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#include <perrno.h>
#include <pprot.h>
#include <pmachine.h>
#include "dirsrv.h"
/* list_acl.c */
extern ACL default_acl;
extern ACL system_acl;
extern ACL override_acl;
extern ACL maint_acl;
extern ACL nullobj_acl;
extern ACL nullcont_acl;
extern ACL nulllink_acl;
extern ACL nulldir_acl;
extern char *acltypes[];
ACL get_container_acl();
int
list_acl(RREQ req, char * command, char *next_word, INPUT in,
char client_dir[], int dir_magic_no)
{
optdecl;
AUTOSTAT_CHARPP(t_namep);
AUTOSTAT_CHARPP(t_optionsp);
int retval = PSUCCESS;/* Return value from subfunctions */
ACL wacl; /* Working access control list */
int aclchk; /* Cached ACL check */
VLINK clink; /* For stepping through links */
P_OBJECT ob = oballoc();
int tmp;
OUTPUT_ST out_st;
OUTPUT out = &out_st;
long n_magic_no; /* magic # of link. XXX currently ignored.*/
reqtoout(req, out);
if (!*t_namep) *t_namep = stcopy("");
if (!*t_namep) out_of_memory();
/* First arg is options. All others are optional. */
/* If a second argument is specified, it is the */
/* link for which the ACL is to be returned */
/* if the OBJECT option is specified, then args */
/* 2-5 identify the object instead of the link. Object ACLs unimplemented,
so we currently suppress those arguments. */
tmp = qsscanf(next_word, "%&'s %&'s %'*s %*d", &*t_optionsp, &*t_namep);
/* Log and return a better message */
if (tmp < 0)
interr_buffer_full();
if((tmp < 1) ||
((tmp < 2) && (!strequal(*t_optionsp,"DIRECTORY")))) {
creply(req,"ERROR too few arguments\n");
plog(L_DIR_PERR,req,"Too few arguments: %s", command);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if (in_select(in, &n_magic_no))
return error_reply(req, "LIST-ACL %'s", p_err_string);
optstart(*t_optionsp);
/* Do we need a better log message? */
plog(L_DIR_REQUEST,req,"LA %s %s", client_dir,*t_namep);
if(opttest("INCLUDE")) {
if(strequal(*t_namep,"SYSTEM")) wacl = system_acl;
else if(strequal(*t_namep,"DEFAULT")) wacl = default_acl;
else if(strequal(*t_namep,"OVERRIDE")) wacl = override_acl;
else if(strequal(*t_namep,"MAINTENANCE")) wacl = maint_acl;
else {
creplyf(req,"FAILURE NOT-FOUND ACL INCLUDED %'s\n",*t_namep);
plog(L_DIR_ERR,req,"INCLUDED ACL not found: %s", *t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
aclchk = srv_check_acl(wacl,NULL,req,"Y",SCA_MISC,NULL,NULL);
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized LIST-ACL: INCLUDED %s", *t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if(wacl == NULL) retval = reply(req,"ACL NONE '' ''\n");
else out_acl(out, wacl);
obfree(ob); ob = NULL;
return(retval);
}
else if(opttest("NAMED")) {
tmp = get_named_acl(*t_namep, &wacl);
if (tmp) {
creplyf(req,"FAILURE NOT-FOUND ACL NAMED %'s\n",*t_namep);
plog(L_DIR_ERR,req,"NAMED ACL not found: %s", *t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
aclchk = srv_check_acl(wacl,NULL,req,"Y",SCA_MISC,NULL,NULL);
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized LIST-ACL: NAMED %s", *t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if(wacl == NULL) retval = reply(req,"ACL NONE '' ''\n");
else out_acl(out, wacl);
aclfree(wacl);
obfree(ob); ob = NULL;
return(retval);
}
else if(opttest("OBJECT")||opttest("CONTAINER")) {
int rsinfo_ret;
rsinfo_ret = dsrobject(req, "ASCII", *t_namep, 0L, 0L, 0,
(struct dsrobject_list_options *) NULL, ob);
#ifdef DIRECTORYCACHING
if (rsinfo_ret) dsrobject_fail++;
#endif
if(rsinfo_ret == DSRFINFO_FORWARDED) {
VLINK fl; /* List of forwarding pointers */
VLINK fp; /* Current forwarding pointer */
fl = ob->forward; ob->forward = NULL;
fp = check_fwd(fl,*t_namep,0);
/* Return forwarded message */
forwarded(req, fl, fp, *t_namep);
/* Free what we don't need */
obfree(ob); ob = NULL;
return PSUCCESS;
}
if(opttest("CONTAINER")) {
wacl = get_container_acl(*t_namep);
}
else {
wacl = ob->acl; ob->acl = NULL;
}
aclchk = srv_check_acl(wacl,NULL,req,"Y",SCA_OBJECT,NULL,NULL);
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized LIST-ACL: OBJECT %s", *t_namep);
aclfree(wacl);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if(wacl == NULL) {
if(opttest("CONTAINER")) out_acl(out, nullcont_acl);
else out_acl(out, nullobj_acl);
}
else out_acl(out, wacl);
obfree(ob); ob = NULL;
return(retval);
}
retval = dsrobject(req, "ASCII", client_dir, 0L, dir_magic_no,
0, (struct dsrobject_list_options *) NULL, ob);
#ifdef DIRECTORYCACHING
if (retval) dsrobject_fail++;
#endif
if(retval == DSRFINFO_FORWARDED) {
obforwarded(req, client_dir, dir_magic_no, ob);
obfree(ob); ob = NULL;
return PSUCCESS;
}
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR,req,"Invalid directory name: %s", client_dir);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if (retval) {
creplyf(req, "FAILURE SERVER-FAILED Could not read directory %'s\n",
client_dir);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
wacl = NULL;
if(opttest("LINK")) {
/* Need to find the link so we can check its ACL */
clink = ob->links;
while(clink) {
if(strequal(clink->name,*t_namep) && clink->linktype != '-')
break;
clink = clink->next;
}
if(!clink) {
clink = ob->ulinks;
while(clink) {
if(strcmp(clink->name,*t_namep) == 0)
break;
clink = clink->next;
}
}
if(!clink) {
creplyf(req,"FAILURE NOT-FOUND LINK %'s",*t_namep);
plog(L_DIR_ERR,req,"Link not found: %s %s", client_dir, *t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
wacl = clink->acl;
aclchk = srv_check_acl(clink->acl,ob->acl,req,"v",SCA_LINK,NULL,NULL);
} else if(opttest("DIRECTORY")) {
wacl = ob->acl;
aclchk = srv_check_acl(ob->acl,NULL,req,"V",SCA_DIRECTORY,client_dir,NULL);
} else {
creply(req,"ERROR invalid option\n");
plog(L_DIR_PERR,req,"Invalid option: %s", command);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
/* If not authorized, say so */
if(!aclchk) {
creply(req,"FAILURE NOT-AUTHORIZED\n");
plog(L_AUTH_ERR,req,"Unauthorized LIST-ACL: %s %s", client_dir,*t_namep);
obfree(ob); ob = NULL;
RETURNPFAILURE;
}
if(wacl == NULL) {
if(opttest("LINK")) /* Link default is diracl */
out_acl(out, nulllink_acl);
else {
out_acl(out, nulldir_acl);
}
} else {
out_acl(out, wacl);
}
obfree(ob); ob = NULL;
return retval;
} /* What does this go to? */

0
prospero/server/next Normal file
View File

234
prospero/server/parameter.c Normal file
View File

@@ -0,0 +1,234 @@
/*
parameter.c
Copyright (c) 1993, the University of Southern California
For copying and distribution information, read the file <usc-copyr.h>
*/
#include <usc-copyr.h>
#include <ardp.h>
#include <pserver.h> /* For #define PSRV_P_PASSWORD */
#include <pfs.h>
#include <plog.h>
#include <psrv.h>
#ifdef PSRV_P_PASSWORD
#include <ppasswd.h>
#endif
#include "dirsrv.h"
#include <perrno.h>
/* Query: PARAMETER [MANDATORY] { GET | SET } <paramname> [<value-token>] */
/* Reply: PARAMETER VALUE <paramname> <value-token>
PARAMETER NOTSET <paramname>
WARNING NOT-FOUND PARAMETER <paramname>
FAILURE NOT-FOUND PARAMETER <paramname>
*/
#ifdef PFS_THREADS
p_th_mutex p_th_mutexP_PARAMETER_MOTD;
#endif
int
parameter(RREQ req, char *command, char *next_word)
{
int tmp;
AUTOSTAT_CHARPP(t_tmpp);
char *t_text;
char *cp;
int mandatory = 0; /* 1 if MANDATORY */
int set = -1; /* 1 for set; 0 for get. */
static char *p_motd = NULL; /* message of the day. MUTEXED with
p_th_mutexP_PARAMETER_MOTD. Init in
dirsrv.c */
tmp = qsscanf(next_word, "%&'s %r", &*t_tmpp, &next_word);
if (tmp < 2)
goto malformed;
if (strequal(*t_tmpp, "MANDATORY")) {
mandatory = 1;
tmp = qsscanf(next_word, "%&'s %r", *t_tmpp, &next_word);
if (tmp < 2)
goto malformed;
}
if (strequal(*t_tmpp, "SET")) set = 1;
else if (strequal (*t_tmpp, "GET")) set = 0;
else goto malformed;
t_text = NULL;
tmp = qsscanf(next_word, "%'&s %'&s %r", &*t_tmpp, &t_text,
&next_word);
if (tmp < 1)
goto malformed;
if (strequal(*t_tmpp, "PASSWORD")) {
if (tmp != 3)
goto malformed;
}
else if (tmp > 2)
goto malformed;
#ifndef NDEBUG
if (tmp >= 2) assert(t_text != NULL);
else assert(t_text == NULL);
#endif
/* *t_tmpp now should contain a variable name. if text was provided, t_text
contains it. */
if (set) plog(L_DIR_UPDATE, req, "%s", command);
else plog(L_DIR_REQUEST, req, "%s", command);
/* Make sure ACLs are initialized properly */
if (!maint_acl) srv_check_acl((ACL) NULL, (ACL) NULL, req, "X", SCA_MISC,NULL,NULL);
if (strequal(*t_tmpp, "MOTD")) {
if (set) {
if (!srv_check_acl(maint_acl,NULL,req,"U",SCA_MISC,NULL,NULL)) {
plog(L_AUTH_ERR, req, "Unauthorized: %s", command);
if (mandatory) {
creplyf(req, "FAILURE NOT-AUTHORIZED %'s\n", command);
RETURNPFAILURE;
} else {
replyf(req, "WARNING NOT-AUTHORIZED %'s\n", command);
return PSUCCESS;
}
}
p_th_mutex_lock(p_th_mutexP_PARAMETER_MOTD);
stfree(p_motd);
p_motd = t_text;
t_text = NULL;
p_th_mutex_unlock(p_th_mutexP_PARAMETER_MOTD);
reply(req, "SUCCESS\n");
} else {
/* Ok to examine the value once; looking at a variable's value is
atomic and need not be mutexed. */
if (p_motd)
replyf(req, "PARAMETER VALUE MOTD %'s\n", p_motd);
else
reply(req, "PARAMETER NOTSET MOTD\n");
}
} else if (strequal(*t_tmpp, "TERMINATE")) {
if (set) {
if (!t_text || !strequal(t_text, "NOW")) {
stfree(t_text); t_text = NULL;
if (mandatory) {
creply(req, "FAILURE BAD-VALUE Must be NOW\n");
RETURNPFAILURE;
} else {
reply(req, "WARNING BAD-VALUE Must be NOW\n");
return PSUCCESS;
}
}
stfree(t_text); t_text = NULL;
if (!srv_check_acl(maint_acl,NULL,req,"T",SCA_MISC,NULL,NULL)) {
plog(L_AUTH_ERR, req, "Unauthorized: %s", command);
if (mandatory) {
creplyf(req, "FAILURE NOT-AUTHORIZED %'s\n", command);
RETURNPFAILURE;
} else {
replyf(req, "WARNING NOT-AUTHORIZED %'s\n", command);
return PSUCCESS;
}
}
plog(L_STATUS,req,"Server killed (terminate message received)",0);
creply(req,"SUCCESS\n");
log_server_stats();
exit(0);
} else {
reply(req, "PARAMETER NOTSET TERMINATE\n");
}
} else if (strequal(*t_tmpp, "RESTART")) {
if (set) {
if (!t_text || !strequal(t_text, "NOW")) {
stfree(t_text); t_text = NULL;
if (mandatory) {
creply(req, "FAILURE BAD-VALUE Must be NOW\n");
RETURNPFAILURE;
} else {
reply(req, "WARNING BAD-VALUE Must be NOW\n");
return PSUCCESS;
}
}
stfree(t_text); t_text = NULL;
if (!srv_check_acl(maint_acl,NULL,req,"S",SCA_MISC,NULL,NULL)) {
plog(L_AUTH_ERR, req, "Unauthorized: %s", command);
if (mandatory) {
creplyf(req, "FAILURE NOT-AUTHORIZED %'s\n", command);
RETURNPFAILURE;
} else {
replyf(req, "WARNING NOT-AUTHORIZED %'s\n", command);
return PSUCCESS;
}
}
plog(L_STATUS,req,"Server restarted (restart message received)",0);
creply(req,"SUCCESS\n");
restart_server(0, (char *) NULL);
} else {
reply(req, "PARAMETER NOTSET RESTART\n");
}
}
#ifdef PSRV_P_PASSWORD
else if (strequal(*t_tmpp, "PASSWORD")) {
int authenticated = 0;
PAUTH auth;
if (!t_text || !next_word)
goto malformed;
/* Check if principal has been authenticated by old password */
for (auth = req->auth_info; auth; auth = auth->next) {
if (auth->ainfo_type == PFSA_P_PASSWORD &&
strequal(t_text, auth->principals->token)) {
authenticated = 1;
break;
}
}
if (set) {
if (/* User authenticated by old password */
authenticated ||
/* 'P' gives right to create and modify password entry */
srv_check_acl(maint_acl,NULL,req,"P",SCA_MISC,NULL,NULL) ||
/* 'p' gives only modify password right */
(srv_check_acl(maint_acl,NULL,req,"p",SCA_MISC,NULL,NULL) &&
get_ppw_entry(t_text))) {
char *passwd = NULL;
qsscanf(next_word, "%'&s", &passwd); /* Unquote */
/* password */
if (set_passwd(t_text, passwd)) {
/* Should never occur */
stfree(t_text); t_text = NULL;
creplyf(req, "UNKNOWN FAILURE\n");
RETURNPFAILURE;
}
stfree(passwd);
reply(req, "SUCCESS\n");
}
else {
stfree(t_text); t_text = NULL;
plog(L_AUTH_ERR, req, "Unauthorized: PARAMETER SET PASSWORD");
if (mandatory) {
creplyf(req, "FAILURE NOT-AUTHORIZED SET PASSWORD\n");
RETURNPFAILURE;
} else {
replyf(req, "WARNING NOT-AUTHORIZED SET PASSWORD\n");
return PSUCCESS;
}
}
}
else {
reply(req, "PARAMETER NOTSET PASSWORD\n");
}
}
#endif
else /* not found */ {
stfree(t_text); t_text = NULL;
if (mandatory) /* set or get */ {
creplyf(req, "FAILURE NOT-FOUND PARAMETER %s\n", *t_tmpp);
RETURNPFAILURE;
} else /* set or get */
replyf(req, "WARNING NOT-FOUND PARAMETER %s\n", *t_tmpp);
}
stfree(t_text); t_text = NULL;
return PSUCCESS;
malformed:
stfree(t_text); t_text = NULL;
return error_reply(req, "Malformed commmand: %'s", command);
}

160
prospero/server/pstart.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*
* Written by bcn 1989 modified 1989-1991
* modified by bcn 1/19/93 to support new argument conventions for dirsrv
* Modified by swa 7/09/93 to take -p# option to specify a port.
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/param.h>
#include <pmachine.h> /* SCOUNIX for socket.h need sys/types.h*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <pwd.h>
#include <unistd.h> /* getuid etc */
#include <pserver.h>
#include <pfs.h> /* For qsscanf */
#include <pprot.h>
char prog[100];
void
main(argc,argv)
int argc;
char *argv[];
{
char *dsargv[11]; /* Args to dirsrv */
int dsargc = 0; /* Count of args to dirsrv */
char prvparg[10]; /* -p%d (%d is file desc) */
char shadowarg[MAXPATHLEN];
char securityarg[MAXPATHLEN];
char datarg[MAXPATHLEN];
char aftparg[MAXPATHLEN];
struct sockaddr_in s_in = {AF_INET};
int prvport = -1;
int alternate_portnum = 0;
int ruid,euid;
struct servent *sp;
struct passwd *pw;
int one = 1;
if (argv[1] && qsscanf(argv[1], "-p#%d", &alternate_portnum) == 1)
++argv, --argc;
if (argc > 2) {
usage:
fprintf(stderr,
"Usage: %s [-p#<alternate-port>] [full-host-name]\n",
argv[0]);
exit(1);
}
strcpy(prog,argv[0]);
ruid = getuid();
euid = geteuid();
/* If root and alternate port wasn't specified, try to bind privileged
port before changing uid */
/* The effective uid needs to be root for bind() to succeed on
the privileged port ; real uid of root isn't enough (bug fixed,
sw@isi.edu, 1 Sept. 1993). */
if(!alternate_portnum && euid == 0) {
assert(P_IS_THIS_THREAD_MASTER()); /*getpwuid MT-Unsafe*/
if ((sp = getservbyname("prospero", "udp")) == 0)
s_in.sin_port = htons((ushort) PROSPERO_PORT);
else s_in.sin_port = sp->s_port;
if ((prvport = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
fprintf(stderr, "pstart: Can't open socket\n");
setsockopt(prvport, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
if (bind(prvport, &s_in, S_AD_SZ) < 0) {
fprintf(stderr, "pstart: Can not bind privileged port\n");
close(prvport);
prvport = -1;
}
}
/* Find the Prospero UID, so we can setuid if we are root */
if((pw = getpwnam(PSRV_USER_ID)) == NULL) {
fprintf(stderr,"%s: Can't find passwd entry for %s.\n",
argv[0],PSRV_USER_ID);
exit(1);
}
/* Don't allow changes to paths unless running as root or */
/* already running as PSRV_USER_ID */
if((ruid != 0) && (ruid != pw->pw_uid) &&
(getenv("PSRV_ROOT") || getenv("PSRV_FSHADOW") ||
getenv("PSRV_FSTORAGE") || getenv("PSRV_FSECURITY") ||
getenv("PSRV_AFTPDIR") ||
getenv("PSRV_AFSDIR") || getenv("PSRV_LOGFILE"))) {
fprintf(stderr,"%s: PSRV_* environment variables set but not authorized.\n",argv[0]);
exit(1);
}
/* Set the uid and gid if necessary */
if((ruid != pw->pw_uid) || (euid != pw->pw_uid)) {
if(setgid(pw->pw_gid)) {
fprintf(stderr,"%s: Can't set gid.\n",argv[0]);
exit(1);
}
if(setuid(pw->pw_uid)) {
fprintf(stderr,"%s: Can't set uid.\n",argv[0]);
exit(1);
}
}
dsargv[0] = "dirsrv"; dsargc++;
/* prvport and alternate_port can't both be specified at once. */
if(prvport >= 0) {
sprintf(prvparg,"-p%d",prvport);
dsargv[dsargc++] = prvparg;
} else if (alternate_portnum) {
sprintf(prvparg,"-p#%d",alternate_portnum);
dsargv[dsargc++] = prvparg;
}
#ifdef P_UNDER_UDIR
sprintf(shadowarg,"-S%s/%s",pw->pw_dir,PSRV_SHADOW);
sprintf(securityarg,"-s%s/%s",pw->pw_dir,PSRV_SECURITY);
sprintf(datarg,"-T%s/%s",pw->pw_dir,PSRV_STORAGE);
dsargv[dsargc++] = shadowarg;
dsargv[dsargc++] = securityarg;
dsargv[dsargc++] = datarg;
#endif P_UNDER_UDIR
#ifdef AFTPUSER
/* Find FTP directory - if error, use AFTPDIRECTORY */
if((pw = getpwnam(AFTPUSER)) != NULL) {
sprintf(aftparg,"-f%s",pw->pw_dir);
dsargv[dsargc++] = aftparg;
}
#endif AFTPUSER
if(argc > 1) {
dsargv[argc++] = "-h";
dsargv[argc++] = argv[1];
}
dsargv[dsargc++] = NULL;
umask(7);
execv(P_DIRSRV_BINARY,dsargv);
/* Execl failed */
exit(1);
}

294
prospero/server/pw_edit.c Normal file
View File

@@ -0,0 +1,294 @@
/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-copyr.h>.
*/
#include <usc-copyr.h>
#include <stdio.h>
#include <string.h>
#include <pfs.h>
#include <pserver.h> /* For #define PSRV_P_PASSWORD */
#include <termios.h>
#include <posix_signal.h>
#include <errno.h>
#ifdef PSRV_P_PASSWORD
#include <ppasswd.h>
/* Possible actions */
#define SET_PASSWD 1
#define DELETE 2
#define LIST 3
char *progname = "pw_edit";
int pfs_debug = 0;
static void abort_pwread(void);
static void abort_prog(void);
void perform_action(int action, char *principal);
int usage();
int read_password(char *prompt, char *pwstr, int pwlen);
int get_principal_name(char *principal);
int display_commands();
/* Program to locally edit server password file.
* -s: set principal's password.
* -d: delete principal's entry.
* -l: list principals in file.
*/
void
main(int argc, char *argv[])
{
char principal[255];
char response[255];
char command[255];
int num, action = 0;
extern int opterr, optind;
extern char *optarg;
char ch;
while ((ch = getopt(argc, argv, "D:s:d:l")) != EOF)
switch(ch) {
case 'D':
pfs_debug = 1; /* Default debug level */
sscanf(optarg,"%d",&pfs_debug);
break;
case 's': /* Set password */
if (action)
usage();
action = SET_PASSWD;
if (optarg[0] == '-') {
printf("pw_edit: option requires an argument -- s\n");
usage();
}
strncpy(principal, optarg, sizeof(principal));
break;
case 'd': /* Delete entry */
if (action)
usage();
action = DELETE;
if (optarg[0] == '-') {
printf("pw_edit: option requires an argument -- d\n");
usage();
}
strncpy(principal, optarg, sizeof(principal));
break;
case 'l': /* List principals */
if (action)
usage();
action = LIST;
break;
case '?':
default:
usage();
}
if (optind != argc)
usage();
if (action) {
perform_action(action, principal);
exit(0);
}
while (1) {
printf("%s: ", progname);
fgets(response, sizeof(response), stdin);
num = sscanf(response, "%s %s %s\n", command, principal, response);
if (num < 1)
continue;
if (num > 2) {
printf("Too many arguments!\n");
display_commands();
continue;
}
if (strequal(command, "s") || strequal(command, "set")) {
if (num < 2)
if (get_principal_name(principal) == PFAILURE)
continue;
perform_action(SET_PASSWD, principal);
continue;
}
if (strequal(command, "d") || strequal(command, "del")) {
if (num < 2)
if (get_principal_name(principal) == PFAILURE)
continue;
perform_action(DELETE, principal);
continue;
}
if (strequal(command, "l") || strequal(command, "list")) {
if (num > 1) {
printf("Too many arguments!\n");
continue;
}
perform_action(LIST, NULL);
continue;
}
if (strequal(command, "q") || strequal(command, "quit")) {
printf("Bye!\n");
break;
}
printf("Illegal command!\n");
display_commands();
}
exit(0);
}
/* Display usage and exit. */
int
usage()
{
fprintf(stderr,
"Usage: %s [-D[#]] {[-s(et) <princ>] | [-d(el) <princ>] | [-l(ist)]}\n",
progname);
exit(1);
}
/* Display possible commands */
int
display_commands()
{
printf("Please enter one of:\n");
printf("\ts(et) [principal] - set principal's password.\n");
printf("\td(el) [principal] - delete principal's entry.\n");
printf("\tl(ist) - list principals.\n");
printf("\tq(uit) - quit.\n");
return 0;
}
/* Perform requested action */
void
perform_action(int action, char *principal)
{
char passwd[255], buf[255];
switch (action) {
case SET_PASSWD:
qsprintf(buf, sizeof(buf), "Password for %s",
principal);
read_password(buf, passwd, sizeof(passwd));
if (set_passwd(principal, passwd) == PSUCCESS)
printf("Password set.\n");
else
perror("Could not access password file");
break;
case DELETE:
if (!get_ppw_entry(principal)) {
printf("Principal %s not found!\n", principal);
break;
}
printf("Really delete entry for principal '%s'? (yes/no): ",
principal);
gets(buf);
if (strcmp(buf, "yes")) {
printf("Password entry NOT deleted!\n");
break;
}
if (delete_ppw_entry(principal) == PSUCCESS)
printf("Password entry for principal '%s' deleted.\n",
principal);
else {
qsprintf(buf, sizeof(buf),
"Could not delete password entry for principal '%s'",
principal);
perror(buf);
}
break;
case LIST:
if (list_ppw_file() == PFAILURE)
perror("Could not access Prospero password file");
break;
default: /* Should never happen */
usage();
}
}
/* Gets principal name */
int
get_principal_name(char *principal)
{
int count = 0;
do {
printf("Principal name: ");
gets(principal);
count++;
} while (principal[0] == '\0' && count < 3);
if (principal[0] == '\0') {
printf("Aborting!\n");
return PFAILURE;
}
else
return PSUCCESS;
}
static struct termios permmodes;
/* Read password for principal princ, and return in pwstr */
int
read_password(char *prompt, char *pwstr, int pwlen)
{
struct termios tempmodes;
int tmp;
if (prompt)
printf("%s: ", prompt);
else
printf("Password: ");
fflush(stdout);
if(tcgetattr(fileno(stdin), &permmodes)) return(errno);
bcopy(&permmodes,&tempmodes,sizeof(struct termios));
tempmodes.c_lflag &= ~(ECHO|ECHONL);
signal(SIGQUIT,abort_pwread);
signal(SIGINT,abort_pwread);
if(tcsetattr(fileno(stdin), TCSANOW, &tempmodes)) return(errno);
*pwstr = '\0';
fgets(pwstr, pwlen, stdin);
pwstr[strlen(pwstr)-1] = '\0'; /* Take off '\n' */
printf("\n");
fflush(stdout);
if(tcsetattr(fileno(stdin), TCSANOW, &permmodes)) return(errno);
signal(SIGQUIT,abort_prog);
signal(SIGINT,abort_prog);
return PSUCCESS;
}
static void abort_pwread(void)
{
tcsetattr(fileno(stdin), TCSANOW, &permmodes);
abort_prog();
}
static void abort_prog(void)
{
printf("Aborted\n");
exit(0);
}
#endif /* PSRV_P_PASSWORD */

View File

@@ -0,0 +1,175 @@
/*
* Copyright (c) 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*
* Written by bcn 1991 to restart server on command or failure
* Modified by bcn 1/20/93 to use new arguments to dirsrv
* Modified by swa 12/93 to not use local buffers or sprintf().
*/
#include <usc-license.h>
#include <stdio.h>
#include <string.h>
#include <errno.h> /* for def of external errno variable */
#include <sys/param.h>
#include <ardp.h>
#include <pfs.h>
#include <pserver.h>
#include <plog.h>
#include <pmachine.h>
#include <psrv.h> /* For close_plog */
#include <pparse.h>
#include "dirsrv.h"
#include <sockettime.h>
/* NOTE: For SOLARIS, this must NOT be <signal.h> which we override
in ../include/signal.h so that sigset_t gets defined.
This is unfortunately neccessary since we are POSIX_SIGNAL
compliant, but not in general (yet) POSIX compliant */
#include <posix_signal.h> /* for SIG_SETMASK & sigset_t*/
/*
* restart server restarts the server by calling exec. Before
* restarting, it logs the current statisitcs which would otherwise
* be lost.
*/
#ifndef NDEBUG
int attemptRestart = 0;
#endif
static char * in_port_str = NULL;
static char * fcount_str = NULL;
void
set_restart_params(int fcount, /* count of # of failures */
int inport /* UDP port # we use. (NOT a descriptor #). */ )
{
assert(P_IS_THIS_THREAD_MASTER());
in_port_str = qsprintf_stcopyr(in_port_str, "-p#%d", inport);
fcount_str = qsprintf_stcopyr(fcount_str, "-F%d",
(fcount < 99999 ? fcount : 99999));
}
void
restart_server(int fcount, char *estring)
{
static int still_going = 0; /* set if restart attempt in progress */
int f;
char *dsargv[50]; /* Args to dirsrv */
int dsargc = 0; /* Count of args to dirsrv */
#ifndef NDEBUG
attemptRestart = 1; /* Set a flag so can debug things */
#endif
if(still_going > 10) exit(1); /* It's the energizer rabbit */
#ifdef TIMEOUT_APPROACH
alarm(0); /*Make sure we dont get interrupted*/
#endif
if(still_going++ == 0 || p__is_out_of_memory) {
/* If first time through */
if (!(p_th_mutex_trylock(p_th_mutexPSRV_LOG))) {
/* Log statistics before we forget them on restart */
log_server_stats();
close_plog();
}
}
/* Close all files except stdin, stdout, and stderr */
/* which should still be /dev/null, and in_port */
/* which we might not be able to reopen */
for (f = 3; f < OPEN_MAX; f++) {
if(f != in_port) (void) close(f);
}
/*dsargv now built at startup in set_restart_params */
dsargv[dsargc++] = "dirsrv";
/* Port to listen on */
if(in_port >= 0) {
dsargv[dsargc++] = in_port_str;
}
if(portname) {
dsargv[dsargc++] = "-p";
dsargv[dsargc++] = portname;
}
if(estring) {
dsargv[dsargc++] = "-E";
dsargv[dsargc++] = estring;
}
if(fcount > 0) {
dsargv[dsargc++] = fcount_str;
}
dsargv[dsargc++] = "-h";
dsargv[dsargc++] = hostname;
dsargv[dsargc++] = "-S";
dsargv[dsargc++] = shadow;
dsargv[dsargc++] = "-T";
dsargv[dsargc++] = pfsdat; /* storage */
if(root && *root) {
dsargv[dsargc++] = "-r";
dsargv[dsargc++] = root;
}
if(aftpdir && *aftpdir) {
dsargv[dsargc++] = "-f";
dsargv[dsargc++] = aftpdir;
}
if(afsdir && *afsdir) {
dsargv[dsargc++] = "-a";
dsargv[dsargc++] = afsdir;
}
/* logfile if changed on command line */
if(logfile_arg) {
dsargv[dsargc++] = "-L";
dsargv[dsargc++] = logfile_arg;
}
dsargv[dsargc++] = NULL;
#ifdef POSIX_SIGNALS
{
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, (sigset_t *)NULL);
}
#else
sigsetmask(0);
#endif /*POSIX_SIGNALS*/
/* Restart the server specifying the appropriate flags */
execv(P_DIRSRV_BINARY,dsargv);
/* If we get here, the exec failed */
/* Oops - cant write to log since we closed it ! */
#ifdef OLDSWA
plog(L_FAILURE,NOREQ,
#else
fprintf(stderr,
#endif
"***Failure - Couldn't restart server %s (%s) - execv exited with \
error # %d, error name %s: - aborting***",
P_DIRSRV_BINARY, estring ? estring : "", errno, unixerrstr()
);
exit(1);
}

388
prospero/server/shadowcvt.c Normal file
View File

@@ -0,0 +1,388 @@
/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <pfs.h>
#include <pserver.h>
#include <pprot.h>
#include <pparse.h>
#include <stdio.h>
#ifndef MAXPATHLEN
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#undef NULL
#endif /* #ifdef CONFLICT... */
#include <sys/param.h> /* XXX This should Change. MAXPATHLEN is too
UNIX-specific. It is almost always 1024,
but we should use MAX_VPATH instead. */
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#ifndef NULL
#include <stddef.h>
#endif /* #ifndef NULL */
#endif /* #ifdef CONFLICT... */
#endif /* #ifndef MAXPATHLEN */
extern char *rindex();
/* These are used by some other routines. We don't ever actually use these
definitions, but functions that we call refer to them, although they
never actually make it into the files we're converting. */
char *aftpdir = "";
char shadow[MAXPATHLEN] = PSRV_FSHADOW;
char dirshadow[MAXPATHLEN] = DSHADOW;
char dircont[MAXPATHLEN] = DCONTENTS;
char pfsdat[MAXPATHLEN] = PSRV_FSTORAGE;
char hostwport[MAXPATHLEN+30] = "THIS SHOULD NOT EVER BE USED; hostwport[]";
/* Host name w/ port if non-standard */
/* shadowcvt.c */
/* Convert v1 format shadow directory files to v5 format. */
/* read shadowcvt.doc before running this program. */
main(argc,argv)
int argc;
char *argv[];
{
int numconv = 0; /* How many files converted successfully? */
char line[MAXPATHLEN];
extern int fseek();
/* server initialization routines. Needed to set stuff to files.*/
qoprintf = srv_qoprintf;
stdio_fseek = fseek;
if (argc != 3) {
fputs("shadowcvt: usage: shadowcvt old-directory \
new-directory < file-name-listing\n", stderr);
exit(1);
}
/* While there's a line with a single filename on it. */
while(scanf(" %s ", line) == 1) {
char infile[MAXPATHLEN], outfile[MAXPATHLEN], outdir[MAXPATHLEN] ;
FILE *in, *out;
char *slashp; /* pointer to last slash in string. */
assert(qsprintf(infile, sizeof infile, "%s/%s", argv[1], line)
<= sizeof infile);
assert(qsprintf(outfile, sizeof outfile, "%s/%s", argv[2], line)
<= sizeof outfile);
strcpy(outdir,outfile);
if ((slashp = rindex(outdir, '/')) == NULL) {
fprintf(stderr, "Can't find a last component in the output file \
%s. Something is very wrong! Aborting execution!\n", outdir);
exit(1);
}
*slashp = '\0';
/* create directory for output file */
if(mkdirs(outdir)) {
fprintf(stderr,
"Couldn't create a directory to hold the output file %s. \
Aborting.", outfile);
exit(1);
}
/* open infile and outfile */
if ((in = locked_fopen(infile, "r")) == NULL) {
fprintf(stderr, "Couldn't open input file %s; aborting \
execution!\n", infile);
exit(1);
}
if ((out = locked_fopen(outfile, "w")) == NULL) {
fprintf(stderr," Couldn't open output file %s;aborting \
execution!\n", outfile);
locked_fclose_A(in,infile,TRUE);
exit(1);
}
if(cvt_dir(infile, in, outfile, out)) {
fprintf(stderr, "Continuing to attempt to convert directory \
information.\n");
} else {
numconv++;
}
locked_fclose_A(in,infile,TRUE);
locked_fclose_A(out,outfile,FALSE);
}
exit(0);
}
static TOKEN tokenize();
static int fdsrdir_v1(char vfs_dirname[], FILE *in, VDIR dir);
int convert_v1_ltype(char l_type[], VLINK cur_link);
cvt_dir(infile, inf, outfile, outf)
char infile[]; /* for reporting error messages */
char outfile[];
FILE *inf, *outf;
{
VDIR_ST dir_st;
VDIR dir = &dir_st;
vdir_init(dir);
/* Read in the directory. */
if (fdsrdir_v1(infile, inf, dir) == 0) {
return fdswdir_v5(outf, dir);
}
RETURNPFAILURE;
}
static TOKEN
tokenize(s)
char *s;
{
TOKEN retval;
char buf[MAX_DIR_LINESIZE];
int tmp = qsscanf(s, "%!!s %r", buf, sizeof buf, &s);
if (tmp < 0)
internal_error("Buffer overflow!");
if (tmp == 0)
return NULL;
if ((retval = tkalloc(buf)) == NULL)
internal_error("tkalloc() out of memory!");
if (tmp == 2)
retval->next = tokenize(s);
return retval;
}
/* Read in a directory. Complaints to stderr. */
static int fdsrdir_v1(char vfs_dirname[], FILE *vfs_dir, VDIR dir)
{
char line[MAX_DIR_LINESIZE];
VLINK cur_link = NULL;
ACL cur_acl = NULL;
ACL prev_acl = NULL;
int tmp;
char truefalse[16];
int bad_link = 0; /* set to 1 if this link is bad and the ACL and
ATTRIBUTEs associated with it should be
skipped. */
int retval = PSUCCESS;
while(fgets(line,MAX_DIR_LINESIZE,vfs_dir)) {
switch(*line) {
case 'V':
tmp = sscanf(line,"VERSION %d",&(dir->version));
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'M': /* Magic Number */
tmp = sscanf(line,"MAGIC-NUMBER %d",&(dir->magic_no));
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'I':
tmp = sscanf(line,"INCLUDE-NATIVE %s",truefalse);
dir->inc_native = VDIN_INCLNATIVE;
if((*truefalse == 'F') || (*truefalse == 'f'))
dir->inc_native = VDIN_NONATIVE;
/* REAL-ONLY - Do not include . and .. */
if((*truefalse == 'R') || (*truefalse == 'r'))
dir->inc_native = VDIN_INCLREAL;
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'A': {
#if 1
char a_acetype[MAX_DIR_LINESIZE];
#else
char a_acltype[MAX_DIR_LINESIZE];
#endif
char a_atype[MAX_DIR_LINESIZE];
char a_rights[MAX_DIR_LINESIZE];
char *p_principals;
extern char *acltypes[];
if (strncmp(line, "ACL ", 4) && bad_link)
break;
cur_acl = acalloc();
/* Code partly taken from parse_owner(). */
p_principals = NULL;
/* V1 dswdir() always wrote at least 3 elements. */
if(qsscanf(line, "ACL %'!!s %'!!s %'!!s %r",
a_acetype, sizeof a_acetype, a_atype, sizeof a_atype,
a_rights, sizeof a_rights, &p_principals) < 3) {
fprintf(stderr,"Bad directory format %s: less than 3 \
arguments to an ACL entry (skipping this ACL line, but converting the rest of \
the directory): %s",
vfs_dirname,line,0);
acfree(cur_acl);
break;
}
for(cur_acl->acetype = 0;acltypes[cur_acl->acetype];
(cur_acl->acetype)++) {
if(strequal(acltypes[cur_acl->acetype],a_acetype))
break;
}
if(acltypes[cur_acl->acetype] == NULL) {
fprintf(stderr,"Bad directory format %s: \
couldn't find acl type %s (skipping this ACL line, but converting the rest of \
the directory): %s",
vfs_dirname,a_acetype, line,0);
acfree(cur_acl);
break;
}
cur_acl->atype = stcopyr(a_atype, cur_acl->atype);
cur_acl->rights = stcopyr(a_rights,cur_acl->rights);
cur_acl->principals = tokenize(unquote(p_principals));
if(prev_acl) {
prev_acl->next = cur_acl;
cur_acl->previous = prev_acl;
}
else if(cur_link) cur_link->acl = cur_acl;
else dir->dacl = cur_acl;
prev_acl = cur_acl;
}
break;
case 'L': {
char l_name[MAX_DIR_LINESIZE];
char l_type[MAX_DIR_LINESIZE];
char l_htype[MAX_DIR_LINESIZE];
char l_host[MAX_DIR_LINESIZE];
char l_ntype[MAX_DIR_LINESIZE];
char l_fname[MAX_DIR_LINESIZE];
prev_acl = NULL; /* So next acl entry is for a new link */
bad_link = 0; /* assume this link is
good until proven guilty :) */
cur_link = vlalloc();
cur_link->f_magic_no = 0; /* in case not set */
tmp = qsscanf(line,
"LINK %'s %c %s %d %*d %s %'s %s %'s %d %d",
l_name, &(cur_link->linktype), l_type,
&(cur_link->dest_exp),
/* &(cur_link->link_exp), */
l_htype,l_host,
l_ntype,l_fname,
&(cur_link->version),
&(cur_link->f_magic_no));
if(tmp >= 9) {
cur_link->name = stcopy(l_name);
cur_link->target = stcopyr(l_type, cur_link->target);
if(convert_v1_ltype(l_type, cur_link)) {
bad_link = 1;
fprintf(stderr, "Directory %s: Did not understand LINK of \
type %s (skipping this link and associated information, but converting the \
rest of the directory): %s", vfs_dirname, l_type, line);
vlfree(cur_link); cur_link = NULL;
break;
}
stfree(cur_link->hosttype); /* Should punt if same */
cur_link->hosttype = stcopy(l_htype);
cur_link->host = stcopy(l_host);
stfree(cur_link->hsonametype); /* Should punt if same */
cur_link->hsonametype = stcopy(l_ntype);
cur_link->hsoname = stcopy(l_fname);
/* if ul, then vl_insert will call ul_insert */
vl_insert(cur_link,dir,VLI_ALLOW_CONF);
/* No need to free cur_link once inserted into dir */
}
else {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
vlfree(cur_link); cur_link = NULL;
}
}
break;
case 'F': { /* Filter attached to previous link */
char f_type;
char f_htype[MAX_DIR_LINESIZE];
char f_host[MAX_DIR_LINESIZE];
char f_ntype[MAX_DIR_LINESIZE];
char f_fname[MAX_DIR_LINESIZE];
int f_vers = 0;
int f_mno = 0;
char f_args[MAX_DIR_LINESIZE];
FILTER cur_fil;
if (strnequal(line, "FILTER ", 7) && bad_link)
break;
if(!cur_link) {
fprintf(stderr, "No reference to previous link. Can't add filter %s: %s",
vfs_dirname,line,0);
break;
}
cur_fil = flalloc();
cur_fil->execution_location = FIL_CLIENT;
cur_fil->link = vlalloc();
f_vers = 0; f_mno = 0;
tmp = sscanf(line,"FILTER %c %s %s %s %s %d %d ARGS ' %[^']",
&f_type, f_htype, f_host, f_ntype, f_fname,
&f_vers, &f_mno, f_args);
if(tmp >= 5) {
cur_fil->pre_or_post = FIL_POST;
switch(f_type) {
case 'd':
cur_fil->pre_or_post = FIL_PRE;
case 'D':
cur_fil->type = FIL_DIRECTORY;
break;
case 'h':
cur_fil->pre_or_post = FIL_PRE;
case 'H':
cur_fil->type = FIL_HIERARCHY;
break;
case 'O':
cur_fil->type = FIL_OBJECT;
break;
case 'U':
cur_fil->type = FIL_UPDATE;
break;
default:
fprintf(stderr, "Bad directory format %s: unknown filter \
type %c: %s", vfs_dirname, f_type, line);
flfree(cur_fil); cur_fil = NULL;
break;
}
cur_fil->link->linktype = f_type;
cur_fil->link->hosttype = stcopyr(f_htype,cur_fil->link->hosttype);
cur_fil->link->host = stcopy(f_host);
stfree(cur_fil->link->hsonametype); /* Should punt if same */
cur_fil->link->hsonametype = stcopy(f_ntype);
cur_fil->link->hsoname = stcopy(f_fname);
cur_fil->link->version = f_vers;
cur_fil->link->f_magic_no = f_mno;
if(tmp == 8) cur_fil->args = tokenize(f_args);
fl_insert(cur_fil,cur_link);
}
else {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
flfree(cur_fil); cur_fil = NULL;
}
} /* Case 'F': */
break;
default: {
fprintf(stderr,"Bad directory format %s: %s", vfs_dirname,line,0);
}
} /* switch */
} /* while */
return retval;
}

View File

@@ -0,0 +1,71 @@
shadowcvt will convert directory service information that is version 1
dirsrv format to version 5 dirsrv format.
To use this program correctly, you need to understand a bit about how
version 1 directory service information was stored.
The SHADOW directory is P_SITE_DIRECTORY/P_SHADOW (or in P_FSHADOW)
(these are constants defined in "include/psite.h").
It contains a copy of the directory hierarchy for all directory
service information stored by the server that's not just taken
directly from the filesystem.
It contains two types of files. One type is in dsdir format, and
contains contents listings for directories. The last component of
these files is always ".directory#contents". The other type is in
dsfile format. It contains attribute information for objects, including
forwarding pointers and attribute information for directories.
dsfile format was never written by the servers.
To do the conversion:
Cd to the 'server' directory in the prospero distribution and type
'make shadowcvt'. This will compile the executable program shadowcvt.
Now make it accessible to your shell under the name 'shadowcvt'. In my
environment, I would do this by typing:
alias shadowcvt $cwd/shadowcvt
Run:
cd P_FSHADOW
find . -type f -print > /tmp/shadow.files
grep -v /.directory#contents$ /tmp/shadow.files
Any files that appear as a result of the grep operation are NOT
dsdir format files. They are presumably dsfile format. You will have
to manually convert them. Note that you will only have these files if
you manually created them in the first place, so you're presumably
already a Prospero wizard, and shouldn't have any problems dealing
with them.
To do the conversion itself:
cd P_SITE_DIRECTORY
grep /.directory#contents$ /tmp/shadow.files \
| shadowcvt P_FSHADOW P_FSHADOW.v5
If any of the .directory#contents files were malformed, you will get
error messages. You shouldn't get any error messages.
You will also get error messages if you made any EXTERNAL links to
files using access-methods other than Anonymous FTP. Such links will
be skipped, as will any line of the .directory#contents files that
yield error messages, and you'll have to manually convert them, but
the rest ofn the file will be converted.
Rename your shadow directory from P_FSHADOW to something else, like
P_FSHADOW.v1. As soon as you do this renaming, prospero requests
arriving to the old server will start to fail, so work quickly until
you reach the end of these instructions. Rename the new shadow
directory from P_FSHADOW.v5 to P_FSHADOW.
Leave P_FSHADOW.v1 around as a backup for a while in case you need to
revert to Version 1 of the server.
Manually kill the old (version 1) server. Now start and run the
version 5 server with "pstart". It is backwards compatible with
version 1 clients, so everything should work immediately.

157
prospero/server/update.c Normal file
View File

@@ -0,0 +1,157 @@
/* Author: bcn@cs.washington.edu, bcn@isi.edu */
/* Modified by swa@isi.edu */
/*
* Copyright (c) 1992, 1993, 1994 by the University of Southern California
*
* For copying and distribution information, please see the file
* <usc-license.h>
*/
#include <usc-license.h>
#define UPDATE_IN_PROGRESS /* this is unimplemented still */
#include <string.h>
#include <ardp.h>
#include <pfs.h>
#include <plog.h>
#include <perrno.h>
#include <psrv.h>
#include <pprot.h> /* for MAXPATHLEN for dirsrv.h */
#include "dirsrv.h"
static int update_name(RREQ req, char *command, char client_dir[],
VDIR dir, char *name, int alllinks,
int *item_count);
int
update(RREQ req, char *command, char *next_word, INPUT in,
char client_dir[], int dir_magic_no)
{
VDIR_ST dir_st;
VDIR dir = &dir_st;
int retval;
int item_count = 0;
long t_magic_no;
char *nextname; /* Next name to be resolved. */
char *dummy; /* Dummy for qsscanf. */
int tmp;
vdir_init(dir);
nextname = "";
tmp = qsscanf(next_word, "'' COMPONENTS%r %r", &dummy, &nextname);
if (tmp < 1)
return error_reply(req, "Bad command format: %'s", command);
if (in_select(in, &t_magic_no))
return error_reply(req, "UPDATE: %'s", p_err_string);
#ifdef UPDATE_IN_PROGRESS
creply(req, "FAILURE SERVER-FAILED UPDATE command not yet fully \
implemented.");
RETURNPFAILURE;
#endif
plog(L_DIR_UPDATE, req, "U %s %s", client_dir, nextname,0);
retval = dsrdir(client_dir,dir_magic_no,dir,NULL,0);
if(retval == DSRFINFO_FORWARDED) {
dforwarded(req, client_dir, dir_magic_no, dir);
return PSUCCESS;
}
/* If not a directory, say so */
if(retval == DSRDIR_NOT_A_DIRECTORY) {
creply(req,"FAILURE NOT-A-DIRECTORY\n");
plog(L_DIR_ERR, req, "Invalid directory name: %s", client_dir,0);
RETURNPFAILURE;
}
if (tmp < 2)
return update_name(req, command, client_dir, dir,
NULL, 1 /* alllinks */, &item_count);
else {
/* A copy of this code is in list.c; if there's a bug here, there's one
there too. */
while (nextname) {
char *son = nextname; /* Start of Name */
char *eon; /* End of Name. */
/* Note the double-quotes -- don't unquote! */
tmp = qsscanf(nextname, "%*'s%r %r", &eon, &nextname);
if (son == eon)
break; /* No more names -- the line must have had trailing
spaces. */
if (tmp == 1) /* No following whitespace; must be the last
name */
nextname = NULL;
else {
assert(tmp == 2);
*eon = '\0'; /* Terminate the name. */
}
if(retval = update_name(req, command, client_dir, dir, son,
/* alllinks */ 0, &item_count))
return retval; /* Don't process any more names if an error
shows up. */
}
}
retval = 0;
if(item_count) retval = dswdir(client_dir,dir);
/* Indicate how many updated */
if(retval) replyf(req,"FAILED to UPDATE %d links\n",item_count,0);
else replyf(req,"UPDATED %d links\n",item_count,0);
vdir_freelinks(dir);
return PSUCCESS;
}
static int
update_name(RREQ req, char *command, char client_dir[], VDIR dir,
char *components, int alllinks, int *item_count)
{
VLINK clink;
FILTER cfil;
int retval;
/* Here we must check for forwarding of each link and */
/* update it to reflect the new target */
clink = dir->links;
while(clink) {
if (clink->linktype == 'N')
continue; /* NATIVE links can't be forwarded. */
if(alllinks || wcmatch(clink->name,components)) {
/* Check for forwarding */
if(retrieve_fp(clink) == PSUCCESS) item_count++;
/* If filters, check them too */
cfil = clink->filters;
while(cfil) {
#ifndef UPDATE_IN_PROGRESS
if(retrieve_fp(cfil) == PSUCCESS) item_count++;
#endif /* UPDATE_IN_PROGRESS */
cfil = cfil->next;
}
}
clink = clink->next;
}
/* here we must process the union links. */
clink = dir->ulinks;
while(clink) {
if (clink->linktype == 'N')
continue; /* NATIVE links can't be forwarded. */
if(alllinks || wcmatch(clink->name,components)) {
/* Check for forwarding */
if(retrieve_fp(clink) == PSUCCESS) item_count++;
/* If filters, check them too ***/
cfil = clink->filters;
while(cfil) {
if(cfil->link && (retrieve_fp(cfil->link) == PSUCCESS))
item_count++;
cfil = cfil->next;
}
}
clink = clink->next;
}
return PSUCCESS;
}

91
prospero/server/version.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 1991, 1992 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-copyr.h>.
*/
#include <usc-copyr.h>
#include <ardp.h>
#include <pserver.h> /* needed for def. of SERVER_DONT_FLAG_V1 */
#include <pfs.h>
#include <plog.h>
#include <pprot.h>
#include <pparse.h>
#include <psrv.h> /* For replyf */
#include "dirsrv.h"
/* Return the # of the client version, if it is one that this version of dirsrv
supports. If it is one that this version cannot support, or if there's an
error, return -1. */
int
version(req, command, next_word)
RREQ req;
char *command;
char *next_word;
{
int tmp;
int client_version;
char t_sw_id[40];
char *cp; /* throw-away temp. ptr. */
#ifndef SERVER_DONT_FLAG_V1
/* Save the last data encountered in order to avoid logging old software
versions quite so many times. */
static char last_oldvers_client_sw_id[40] = "";
static long last_oldvers_client_host = 0L;
#endif
t_sw_id[0] = '\0';
tmp = qsscanf(next_word,"%d %'!!s %r",&client_version,
t_sw_id, sizeof t_sw_id, &cp);
/* Save sw_id before checking tmp so we know how generated */
if(*t_sw_id) req->peer_sw_id = stcopyr(t_sw_id,req->peer_sw_id);
if (tmp < 0) {
interr_buffer_full();
return -1;
}
else if (tmp == 0) {
replyf(req,"VERSION %d %s\n", MAX_VERSION,PFS_SW_ID);
return MAX_VERSION;
} else if (tmp == 3) {
error_reply(req, "VERSION command takes at most 2 arguments,\
but we received: %'s", command);
return -1;
}
assert(tmp == 1 || tmp == 2); /* The client must want us to use
a certain version of the
protocol. */
if(client_version == MAX_VERSION) return client_version;
if((client_version < MAX_VERSION) &&
(client_version >= MIN_VERSION)) {
#ifndef SERVER_DONT_FLAG_V1
if ((last_oldvers_client_host != req->peer_addr.s_addr)
|| !strequal(last_oldvers_client_sw_id,t_sw_id)) {
/* Attempt to reduce the # of unnecessary repeated messages logged.
*/
plog(L_DIR_PWARN, req, "Old version in use: %d %s%s",
client_version,
(t_sw_id[0] ? ", by a client with software ID " : ""),
t_sw_id, 0);
qsprintf(last_oldvers_client_sw_id,
sizeof last_oldvers_client_sw_id, "%s", t_sw_id);
last_oldvers_client_host = req->peer_addr.s_addr;
}
#endif /* SERVER_DONT_FLAG_V1 */
return client_version;
}
if(MAX_VERSION == MIN_VERSION)
creplyf(req,"VERSION-NOT-SUPPORTED TRY %d",MAX_VERSION);
else creplyf(req,"VERSION-NOT-SUPPORTED TRY %d-%d",
MIN_VERSION,MAX_VERSION);
plog(L_DIR_PERR, req,
"Unimplemented version in use: %d %s%s",
client_version,
(t_sw_id[0] ? ", by a client with software ID " : ""),
t_sw_id, 0);
return -1;
}

386
prospero/server/xyz Normal file
View File

@@ -0,0 +1,386 @@
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
ardp: udp/dirsrv unknown service - using 1525
default udp port is 1525
In ardp_send - sending to localhost
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/pfsdat/local_vsystems/bunyip/VS-DESCRIPTION'\nLIST VERIFY COMPONENTS\n
ardp: udp/dirsrv unknown service - using 1525
default udp port is 1525
Sending message (cid=17467) (seq=1) to 127.0.0.1(1525)...Sent.
Received packet from 127.0.0.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 127.0.0.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17467)
The complete response has been received.
Acknowledging final packet to 127.0.0.1(1525)
Sending message (ACK only) (cid=17467) (seq=0) to 127.0.0.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nNONE-FOUND\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to localhost
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/pfsdat/local_vsystems/bunyip/VS-DESCRIPTION'\nLIST '' COMPONENTS\n
Sending message (cid=17468) (seq=1) to 127.0.0.1(1525)...Sent.
Received packet from 127.0.0.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 127.0.0.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17468)
The complete response has been received.
Acknowledging final packet to 127.0.0.1(1525)
Sending message (ACK only) (cid=17468) (seq=0) to 127.0.0.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L SYMBOLIC HOME VIRTUAL-SYSTEM #'/INET/EDU/ISI/bunyip' ASCII '/' 0\nLINK L DIRECTORY ROOT INTERNET-D mocha-int.bunyip.com ASCII '/pfs/pfsdat/local_vsystems/bunyip' 0\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/pfsdat/local_vsystems/bunyip'\nLIST VERIFY COMPONENTS\n
Sending message (cid=17469) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17469)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17469) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nNONE-FOUND\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/pfsdat/local_vsystems/bunyip'\nLIST '' COMPONENTS MENU/debug\n
Sending message (cid=17470) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17470)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17470) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L DIRECTORY MENU INTERNET-D mocha-int.bunyip.com ASCII '/pfs/info-tree' 0\nUNRESOLVED debug\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/info-tree'\nLIST '' COMPONENTS debug\n
Sending message (cid=17471) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17471)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17471) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L DIRECTORY debug INTERNET-D MOCHA.BUNYIP.COM ASCII '/pfs/info-tree/debug' 0\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to MOCHA.BUNYIP.COM
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/info-tree/debug'\nLIST VERIFY COMPONENTS\n
Sending message (cid=17472) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17472)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17472) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nNONE-FOUND\n
weaseld(8691) [ 1 Jul 1994 05:45:27 GMT]: ready to accept connections.
weaseld(8691) [ 1 Jul 1994 05:45:34 GMT]: connection from 192.197.208.1 on remote port 1355: access granted.
weaseld(8691) [ 1 Jul 1994 05:45:34 GMT]: handle_request: request is `MOCHA.BUNYIP.COM:://pfs/info-tree/debug/routledge alexander'.
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to MOCHA.BUNYIP.COM
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/info-tree/debug'\nLIST ATTRIBUTES COMPONENTS routledge\n
Sending message (cid=17473) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17473)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17473) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L DIRECTORY routledge INTERNET-D mocha-int.bunyip.com ASCII ARCHIE 0\nATTRIBUTE LINK APPLICATION MENU-ITEM-DESCRIPTION SEQUENCE routledge\nATTRIBUTE LINK APPLICATION OBJECT-INTERPRETATION SEQUENCE SEARCH\nATTRIBUTE LINK APPLICATION QUERY-METHOD SEQUENCE find(string',maxhits)' FIND(${maxhits}',${maxhits},0,routledge)' ${string} *\nATTRIBUTE LINK APPLICATION QUERY-ARGUMENT SEQUENCE maxhits Maximum' number of files to return' int %d range(1',100)' 100\nATTRIBUTE LINK APPLICATION QUERY-ARGUMENT SEQUENCE string Search' string mandatory' char* %50[^'/]'\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO BUNYIP-POSE-AS ASCII ARCHIE 0\n
Sending message (cid=17474) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17474)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17474) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nNONE-FOUND\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII ARCHIE\nLIST ATTRIBUTES COMPONENTS FIND(100',100,0,routledge)'/alexander/*\n
Sending message (cid=17475) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17475)
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 2 of 2 (cid=17475)
Packets now received through 2
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17475) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L OBJECT Hardback' ' INTERNET-D MOCHA.BUNYIP.COM ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4092,TEXT,routledge)' 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LEN SEQUENCE 4092\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LINES SEQUENCE 131\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SCORE SEQUENCE 1000\nATTRIBUTE CACHED APPLICATION WAIS_DOC_VERSION SEQUENCE -1\nATTRIBUTE CACHED APPLICATION WAIS_DOC_BESTMATCH SEQUENCE 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_DATE SEQUENCE 2099534\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SOURCE SEQUENCE '/pfs/info-tree/www.thomson/DATABASES/routledge/products/routledge'\nATTRIBUTE CACHED APPLICATION WAIS_DOC_TYPES SEQUENCE TEXT\nATTRIBUTE OBJECT INTRINSIC BUNYIP-HEADLINE SEQUENCE Title Author-Name Publisher-Organization-Name ISBN Binding-Format\nLINK
Packet 2:
L OBJECT Paperback' ' INTERNET-D MOCHA.BUNYIP.COM ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4220,TEXT,routledge)' 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LEN SEQUENCE 4220\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LINES SEQUENCE 133\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SCORE SEQUENCE 9\nATTRIBUTE CACHED APPLICATION WAIS_DOC_VERSION SEQUENCE -1\nATTRIBUTE CACHED APPLICATION WAIS_DOC_BESTMATCH SEQUENCE 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_DATE SEQUENCE 2100166\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SOURCE SEQUENCE '/pfs/info-tree/www.thomson/DATABASES/routledge/products/routledge'\nATTRIBUTE CACHED APPLICATION WAIS_DOC_TYPES SEQUENCE TEXT\nATTRIBUTE OBJECT INTRINSIC BUNYIP-HEADLINE SEQUENCE Title Author-Name Publisher-Organization-Name ISBN Binding-Format\n
0Hardback MOCHA.BUNYIP.COM::/ARCHIE/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4092,TEXT,routledge) mocha-int.bunyip.com 6969
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to MOCHA.BUNYIP.COM
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO CONTENTS ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4092,TEXT,routledge)' 0\n
Sending message (cid=17476) (seq=1) to 192.197.208.1(1525)...Sent.
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17476)
Waiting for reply...Received packet from 192.197.208.1
Packet 2 of 0 (cid=17476)
Packets now received through 2
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 3 of 3 (cid=17476)
Packets now received through 3
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17476) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED title Alexander' the Great: The Invisible Enemy'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-title Alexander' the Great'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED sub-title A' Biography'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-blurb `O'''Brien has combined faultless scholarship with poetic vision to penetrate the events of Alexander''s extraordinary life and reveal the tragic pattern obscured by these tumultous events. This is not only biography; it is art.'' F Salvidio'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED long-blurb Alexander' and Dionysus:The Invisible Enemy differs from other biographies of Alexander in its assessment of the role of alcohol in his life. O''Brien uses the the figure of Dionysus as a symbol of the destructive effects of alchohol on Alexander''s psyche. The deity serves as an agent through whom a cluster of ambivalent considerations is explored: the heroic and the Dionysiac, the rational and the irrational, male and female, sanity and madness. Alexander''s story unfolds as a tragedy in the Aristotelian sense of the word. Alexander is treated from birth to death as a total personality.
Packet 2:
His culture, his gods, his parents, his aspirations, his exploits, his fears, his insecurities, his sexuality, his drinking, and the psychology of alcoholism are examined from an interdisciplinary perspective. The book utilises recent discoveries in archaeology and incorporates new interpretations from anthropology, psychology, mythology, philosphy and literature. The historical context provides a structure for these diverese insights. Key passages in the narratvie are illuminated by telling quotations from Homer and Euripides, the authors known to have constituted Alexander''s favourite reading. John Maxwell O''Brien is thus also able to delineate broadly the thought processes of Greek antiquity.'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED version 1\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED original-publication-date 20'/08/92'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED new-publication-date 01'/09/94 Publication City: London'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED isbn 0415072549\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED language English\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED readership '/OMARK'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-code-routled
Packet 3:
ge 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED author-name John' Maxwell O''Brien,'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publisher-organization-name Routledge\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED trim 234x156\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED pages 360\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED illustrations-bw 7' maps and tables'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED binding-format Hardback\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED document-toc '/OCONT'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-main 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-secondary 01040\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED endorsement '''O''Brien''s biography of Alexander is meticulous, thorough, and expressed with great care and grace.'' - Robert Emmet Meagher, author of Mortal Vision: The Wisdom of Euripides.'\nATTRIBUTE OBJECT INTRINSIC ACCESS-METHOD SEQUENCE PROSPERO-CONTENTS '' '' '' ''\n
0Paperback MOCHA.BUNYIP.COM::/ARCHIE/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4220,TEXT,routledge) mocha-int.bunyip.com 6969
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to MOCHA.BUNYIP.COM
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO CONTENTS ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4220,TEXT,routledge)' 0\n
Sending message (cid=17477) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17477)
Waiting for reply...Received packet from 192.197.208.1
Packet 2 of 0 (cid=17477)
Packets now received through 2
Waiting for reply...Received packet from 192.197.208.1
Packet 3 of 0 (cid=17477)
Packets now received through 3
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 4 of 4 (cid=17477)
Packets now received through 4
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17477) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED title Alexander' the Great: The Invisible Enemy'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-title Alexander' the Great'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED sub-title A' Biography'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-blurb `O'''Brien has combined faultless scholarship with poetic vision to penetrate the events of Alexander''s extraordinary life and reveal the tragic pattern obscured by these tumultous events. This is not only biography; it is art.'' F Salvidio'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED long-blurb Alexander' and Dionysus:The Invisible Enemy differs from other biographies of Alexander in its assessment of the role of alcohol in his life. O''Brien uses the figure of Dionysus as a symbol of the destructive effects of alchohol on Alexander''s psyche. The deity serves as an agent through whom a cluster of ambivalent considerations is explored: the heroic and the Dionysiac, the rational and the irrational, male and female, sanity and madness. Alexander''s story unfolds as a tragedy in the Aristotelian sense of the word. Alexander is treated from birth to death as a total personality. His
Packet 2:
culture, his gods, his parents, his aspirations, his exploits, his fears, his insecurities, his sexuality, his drinking, and the psychology of alcoholism are examined from an interdisciplinary perspective. The book utilises recent discoveries in archaeology and incorporates new interpretations from anthropology, psychology, mythology, philosphy and literature. The historical context provides a structure for these diverese insights. Key passages in the narratvie are illuminated by telling quotations from Homer and Euripides, the authors known to have constituted Alexander''s favourite reading. John Maxwell O''Brien is thus also able to delineate broadly the thought processes of Greek antiquity.'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED version 1\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publication-status NYP\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED new-publication-date 01'/09/94 Publication City: London'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED isbn 0415106176\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED language English\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED readership '/OMARK'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-code-routledge 03042\nATTRIBUTE
Packet 3:
OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED author-name John' Maxwell O''Brien, Queens College of the City University of New York'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publisher-organization-name Routledge\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED trim 234x156\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED pages 358\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED illustrations-bw 7' maps and tables'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED binding-format Paperback\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED document-toc '/OCONT'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-main 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-secondary 01040\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-name Paul' A. Gilster, The News and Observer'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-quote `What' happened to Alexander? O''Brien''s answer is mesmerising... he brings to the tale a sense of fatalism that Euripides would understand.'''\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED endorsement `a' minutely researched book ... lucid and compelling'' - The Independent on Sunday'\nATTRIBUTE OBJECT INTRINSIC ACCESS-METHOD SEQUENC
Packet 4:
E PROSPERO-CONTENTS '' '' '' ''\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO BUNYIP-POSE-AS ASCII ARCHIE 0\n
Sending message (cid=17478) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17478)
Waiting for reply...Received packet from 192.197.208.1
Packet 2 of 0 (cid=17478)
Packets now received through 2
Waiting for reply...Received packet from 192.197.208.1
Packet 3 of 0 (cid=17478)
Packets now received through 3
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 4 of 4 (cid=17478)
Packets now received through 4
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17478) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED title Alexander' the Great: The Invisible Enemy'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-title Alexander' the Great'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED sub-title A' Biography'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-blurb `O'''Brien has combined faultless scholarship with poetic vision to penetrate the events of Alexander''s extraordinary life and reveal the tragic pattern obscured by these tumultous events. This is not only biography; it is art.'' F Salvidio'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED long-blurb Alexander' and Dionysus:The Invisible Enemy differs from other biographies of Alexander in its assessment of the role of alcohol in his life. O''Brien uses the figure of Dionysus as a symbol of the destructive effects of alchohol on Alexander''s psyche. The deity serves as an agent through whom a cluster of ambivalent considerations is explored: the heroic and the Dionysiac, the rational and the irrational, male and female, sanity and madness. Alexander''s story unfolds as a tragedy in the Aristotelian sense of the word. Alexander is treated from birth to death as a total personality. His
Packet 2:
culture, his gods, his parents, his aspirations, his exploits, his fears, his insecurities, his sexuality, his drinking, and the psychology of alcoholism are examined from an interdisciplinary perspective. The book utilises recent discoveries in archaeology and incorporates new interpretations from anthropology, psychology, mythology, philosphy and literature. The historical context provides a structure for these diverese insights. Key passages in the narratvie are illuminated by telling quotations from Homer and Euripides, the authors known to have constituted Alexander''s favourite reading. John Maxwell O''Brien is thus also able to delineate broadly the thought processes of Greek antiquity.'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED version 1\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publication-status NYP\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED new-publication-date 01'/09/94 Publication City: London'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED isbn 0415106176\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED language English\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED readership '/OMARK'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-code-routledge 03042\nATTRIBUTE
Packet 3:
OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED author-name John' Maxwell O''Brien, Queens College of the City University of New York'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publisher-organization-name Routledge\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED trim 234x156\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED pages 358\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED illustrations-bw 7' maps and tables'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED binding-format Paperback\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED document-toc '/OCONT'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-main 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-secondary 01040\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-name Paul' A. Gilster, The News and Observer'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-quote `What' happened to Alexander? O''Brien''s answer is mesmerising... he brings to the tale a sense of fatalism that Euripides would understand.'''\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED endorsement `a' minutely researched book ... lucid and compelling'' - The Independent on Sunday'\nATTRIBUTE OBJECT INTRINSIC ACCESS-METHOD SEQUENC
Packet 4:
E PROSPERO-CONTENTS '' '' '' ''\n
.
weaseld(8691) [ 1 Jul 1994 05:45:44 GMT]: handle_request: request succeeded.
weaseld(8691) [ 1 Jul 1994 05:45:44 GMT]: handle_transaction: handle_request() finished.
weaseld(8691) [ 1 Jul 1994 06:06:58 GMT]: connection from 192.197.208.1 on remote port 1439: access granted.
weaseld(8691) [ 1 Jul 1994 06:06:58 GMT]: handle_request: request is `MOCHA.BUNYIP.COM:://pfs/info-tree/debug/routledge alexander'.
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to MOCHA.BUNYIP.COM
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII '/pfs/info-tree/debug'\nLIST ATTRIBUTES COMPONENTS routledge\n
Sending message (cid=17479) (seq=1) to 192.197.208.1(1525)...Sent.
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Ack requested
Packet 1 of 1 (cid=17479)
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17479) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L DIRECTORY routledge INTERNET-D mocha-int.bunyip.com ASCII ARCHIE 0\nATTRIBUTE LINK APPLICATION MENU-ITEM-DESCRIPTION SEQUENCE routledge\nATTRIBUTE LINK APPLICATION OBJECT-INTERPRETATION SEQUENCE SEARCH\nATTRIBUTE LINK APPLICATION QUERY-METHOD SEQUENCE find(string',maxhits)' FIND(${maxhits}',${maxhits},0,routledge)' ${string} *\nATTRIBUTE LINK APPLICATION QUERY-ARGUMENT SEQUENCE maxhits Maximum' number of files to return' int %d range(1',100)' 100\nATTRIBUTE LINK APPLICATION QUERY-ARGUMENT SEQUENCE string Search' string mandatory' char* %50[^'/]'\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO BUNYIP-POSE-AS ASCII ARCHIE 0\n
Sending message (cid=17480) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17480)
Waiting for reply...Received packet from 192.197.208.1
Packet 2 of 0 (cid=17480)
Packets now received through 2
Waiting for reply...Received packet from 192.197.208.1
Packet 3 of 0 (cid=17480)
Packets now received through 3
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 4 of 4 (cid=17480)
Packets now received through 4
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17480) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED title Alexander' the Great: The Invisible Enemy'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-title Alexander' the Great'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED sub-title A' Biography'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-blurb `O'''Brien has combined faultless scholarship with poetic vision to penetrate the events of Alexander''s extraordinary life and reveal the tragic pattern obscured by these tumultous events. This is not only biography; it is art.'' F Salvidio'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED long-blurb Alexander' and Dionysus:The Invisible Enemy differs from other biographies of Alexander in its assessment of the role of alcohol in his life. O''Brien uses the figure of Dionysus as a symbol of the destructive effects of alchohol on Alexander''s psyche. The deity serves as an agent through whom a cluster of ambivalent considerations is explored: the heroic and the Dionysiac, the rational and the irrational, male and female, sanity and madness. Alexander''s story unfolds as a tragedy in the Aristotelian sense of the word. Alexander is treated from birth to death as a total personality. His
Packet 2:
culture, his gods, his parents, his aspirations, his exploits, his fears, his insecurities, his sexuality, his drinking, and the psychology of alcoholism are examined from an interdisciplinary perspective. The book utilises recent discoveries in archaeology and incorporates new interpretations from anthropology, psychology, mythology, philosphy and literature. The historical context provides a structure for these diverese insights. Key passages in the narratvie are illuminated by telling quotations from Homer and Euripides, the authors known to have constituted Alexander''s favourite reading. John Maxwell O''Brien is thus also able to delineate broadly the thought processes of Greek antiquity.'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED version 1\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publication-status NYP\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED new-publication-date 01'/09/94 Publication City: London'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED isbn 0415106176\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED language English\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED readership '/OMARK'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-code-routledge 03042\nATTRIBUTE
Packet 3:
OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED author-name John' Maxwell O''Brien, Queens College of the City University of New York'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publisher-organization-name Routledge\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED trim 234x156\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED pages 358\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED illustrations-bw 7' maps and tables'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED binding-format Paperback\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED document-toc '/OCONT'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-main 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-secondary 01040\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-name Paul' A. Gilster, The News and Observer'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-quote `What' happened to Alexander? O''Brien''s answer is mesmerising... he brings to the tale a sense of fatalism that Euripides would understand.'''\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED endorsement `a' minutely researched book ... lucid and compelling'' - The Independent on Sunday'\nATTRIBUTE OBJECT INTRINSIC ACCESS-METHOD SEQUENC
Packet 4:
E PROSPERO-CONTENTS '' '' '' ''\n
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nDIRECTORY ASCII ARCHIE\nLIST ATTRIBUTES COMPONENTS FIND(100',100,0,routledge)'/alexander/*\n
Sending message (cid=17481) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17481)
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 2 of 2 (cid=17481)
Packets now received through 2
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17481) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nLINK L OBJECT Hardback' ' INTERNET-D MOCHA.BUNYIP.COM ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06h0 4092 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4092,TEXT,routledge)' 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LEN SEQUENCE 4092\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LINES SEQUENCE 131\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SCORE SEQUENCE 1000\nATTRIBUTE CACHED APPLICATION WAIS_DOC_VERSION SEQUENCE -1\nATTRIBUTE CACHED APPLICATION WAIS_DOC_BESTMATCH SEQUENCE 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_DATE SEQUENCE 2099534\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SOURCE SEQUENCE '/pfs/info-tree/www.thomson/DATABASES/routledge/products/routledge'\nATTRIBUTE CACHED APPLICATION WAIS_DOC_TYPES SEQUENCE TEXT\nATTRIBUTE OBJECT INTRINSIC BUNYIP-HEADLINE SEQUENCE Title Author-Name Publisher-Organization-Name ISBN Binding-Format\nLINK
Packet 2:
L OBJECT Paperback' ' INTERNET-D MOCHA.BUNYIP.COM ASCII ARCHIE'/ITEM/WAIS/(%01%0blocalhost:0%02A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%03o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%04%0blocalhost:0%05A%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2froutledge%06o449738 453958 %2fexport%2farchie%2fsrc%2f3.0%2farchie%2fpfs%2finfo-tree%2fwww.thomson%2fDATABASES%2froutledge%2fproducts%2fcatalog2.txt%07%01%00,4220,TEXT,routledge)' 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LEN SEQUENCE 4220\nATTRIBUTE CACHED APPLICATION WAIS_DOC_LINES SEQUENCE 133\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SCORE SEQUENCE 9\nATTRIBUTE CACHED APPLICATION WAIS_DOC_VERSION SEQUENCE -1\nATTRIBUTE CACHED APPLICATION WAIS_DOC_BESTMATCH SEQUENCE 0\nATTRIBUTE CACHED APPLICATION WAIS_DOC_DATE SEQUENCE 2100166\nATTRIBUTE CACHED APPLICATION WAIS_DOC_SOURCE SEQUENCE '/pfs/info-tree/www.thomson/DATABASES/routledge/products/routledge'\nATTRIBUTE CACHED APPLICATION WAIS_DOC_TYPES SEQUENCE TEXT\nATTRIBUTE OBJECT INTRINSIC BUNYIP-HEADLINE SEQUENCE Title Author-Name Publisher-Organization-Name ISBN Binding-Format\n
3WAIS file -- can't do this yet.
p__get_pauth(): Error in P_PASSWORD authentication: Cannot open psession file /home/staff/bajan/.psession_12
In ardp_send - sending to mocha-int.bunyip.com
Packet 1:
VERSION\nVERSION 5 ggB(P53.3Mar94)\nAUTHENTICATE '' UNAUTHENTICATED bajan\nGET-OBJECT-INFO BUNYIP-POSE-AS ASCII ARCHIE 0\n
Sending message (cid=17482) (seq=1) to 192.197.208.1(1525)...Sent.
Received packet from 192.197.208.1
Service asked us to wait 900 seconds
Current queue position on server is 1
Received packet from 192.197.208.1
Service asked us to wait 180 seconds
Waiting for reply...Received packet from 192.197.208.1
Service asked us to wait 0 seconds
Packet 1 of 0 (cid=17482)
Waiting for reply...Received packet from 192.197.208.1
Packet 2 of 0 (cid=17482)
Packets now received through 2
Waiting for reply...Received packet from 192.197.208.1
Packet 3 of 0 (cid=17482)
Packets now received through 3
Waiting for reply...Received packet from 192.197.208.1
Ack requested
Packet 4 of 4 (cid=17482)
Packets now received through 4
The complete response has been received.
Acknowledging final packet to 192.197.208.1(1525)
Sending message (ACK only) (cid=17482) (seq=0) to 192.197.208.1(1525)...Sent.
Packets received...Packet 1:
VERSION 5 P53.11May94\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED title Alexander' the Great: The Invisible Enemy'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-title Alexander' the Great'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED sub-title A' Biography'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED short-blurb `O'''Brien has combined faultless scholarship with poetic vision to penetrate the events of Alexander''s extraordinary life and reveal the tragic pattern obscured by these tumultous events. This is not only biography; it is art.'' F Salvidio'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED long-blurb Alexander' and Dionysus:The Invisible Enemy differs from other biographies of Alexander in its assessment of the role of alcohol in his life. O''Brien uses the figure of Dionysus as a symbol of the destructive effects of alchohol on Alexander''s psyche. The deity serves as an agent through whom a cluster of ambivalent considerations is explored: the heroic and the Dionysiac, the rational and the irrational, male and female, sanity and madness. Alexander''s story unfolds as a tragedy in the Aristotelian sense of the word. Alexander is treated from birth to death as a total personality. His
Packet 2:
culture, his gods, his parents, his aspirations, his exploits, his fears, his insecurities, his sexuality, his drinking, and the psychology of alcoholism are examined from an interdisciplinary perspective. The book utilises recent discoveries in archaeology and incorporates new interpretations from anthropology, psychology, mythology, philosphy and literature. The historical context provides a structure for these diverese insights. Key passages in the narratvie are illuminated by telling quotations from Homer and Euripides, the authors known to have constituted Alexander''s favourite reading. John Maxwell O''Brien is thus also able to delineate broadly the thought processes of Greek antiquity.'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED version 1\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publication-status NYP\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED new-publication-date 01'/09/94 Publication City: London'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED isbn 0415106176\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED language English\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED readership '/OMARK'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-code-routledge 03042\nATTRIBUTE
Packet 3:
OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED author-name John' Maxwell O''Brien, Queens College of the City University of New York'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED publisher-organization-name Routledge\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED trim 234x156\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED pages 358\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED illustrations-bw 7' maps and tables'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED binding-format Paperback\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED document-toc '/OCONT'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-main 03042\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED subject-secondary 01040\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-name Paul' A. Gilster, The News and Observer'\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED reviewer-quote `What' happened to Alexander? O''Brien''s answer is mesmerising... he brings to the tale a sense of fatalism that Euripides would understand.'''\nATTRIBUTE OBJECT INTRINSIC CONTENTS SEQUENCE TAGGED endorsement `a' minutely researched book ... lucid and compelling'' - The Independent on Sunday'\nATTRIBUTE OBJECT INTRINSIC ACCESS-METHOD SEQUENC
Packet 4:
E PROSPERO-CONTENTS '' '' '' ''\n
.
weaseld(8691) [ 1 Jul 1994 06:07:07 GMT]: handle_request: request succeeded.
weaseld(8691) [ 1 Jul 1994 06:07:07 GMT]: handle_transaction: handle_request() finished.