archie/prospero/server/ed_obj_info.c
2024-05-27 16:13:40 +02:00

256 lines
7.3 KiB
C

/*
* 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;
}