use of org.exist.security.EffectiveSubject in project exist by eXist-db.
the class ResourceFunctionExecutorImpl method getEffectiveSubject.
/**
* If the compiled xquery is setUid and/or setGid
* we return the EffectiveSubject that should be used
* for execution
*
* @param xquery The XQuery to determine the effective subject for
* @return Maybe an effective subject or empty if there is no setUid or setGid bits
*/
private Optional<EffectiveSubject> getEffectiveSubject(final CompiledXQuery xquery) {
final Optional<EffectiveSubject> effectiveSubject;
final Source src = xquery.getContext().getSource();
if (src instanceof DBSource) {
final DBSource dbSrc = (DBSource) src;
final Permission perm = dbSrc.getPermissions();
if (perm.isSetUid()) {
if (perm.isSetGid()) {
// setUid and SetGid
effectiveSubject = Optional.of(new EffectiveSubject(perm.getOwner(), perm.getGroup()));
} else {
// just setUid
effectiveSubject = Optional.of(new EffectiveSubject(perm.getOwner()));
}
} else if (perm.isSetGid()) {
// just setGid, so we use the current user as the effective user
effectiveSubject = Optional.of(new EffectiveSubject(xquery.getContext().getBroker().getCurrentSubject(), perm.getGroup()));
} else {
effectiveSubject = Optional.empty();
}
} else {
effectiveSubject = Optional.empty();
}
return effectiveSubject;
}
use of org.exist.security.EffectiveSubject in project exist by eXist-db.
the class ResourceFunctionExecutorImpl method execute.
@Override
public Sequence execute(final ResourceFunction resourceFunction, final Iterable<TypedArgumentValue> arguments, final HttpRequest request) throws RestXqServiceException {
final RestXqServiceCompiledXQueryCache cache = RestXqServiceCompiledXQueryCacheImpl.getInstance();
CompiledXQuery xquery = null;
ProcessMonitor processMonitor = null;
try (final DBBroker broker = getBrokerPool().getBroker()) {
// ensure we can execute the function before going any further
checkSecurity(broker, resourceFunction.getXQueryLocation());
// get a compiled query service from the cache
xquery = cache.getCompiledQuery(broker, resourceFunction.getXQueryLocation());
// find the function that we will execute
final UserDefinedFunction fn = findFunction(xquery, resourceFunction.getFunctionSignature());
final XQueryContext xqueryContext = xquery.getContext();
// set the request object - can later be used by the EXQuery Request Module
xqueryContext.setAttribute(EXQ_REQUEST_ATTR, request);
// TODO this is a workaround?
declareVariables(xqueryContext);
// START workaround: evaluate global variables in modules, as they are reset by XQueryContext.reset()
final Expression rootExpr = xqueryContext.getRootExpression();
for (int i = 0; i < rootExpr.getSubExpressionCount(); i++) {
final Expression subExpr = rootExpr.getSubExpression(i);
if (subExpr instanceof VariableDeclaration) {
subExpr.eval(null);
}
}
// END workaround
// setup monitoring
processMonitor = broker.getBrokerPool().getProcessMonitor();
xqueryContext.getProfiler().traceQueryStart();
processMonitor.queryStarted(xqueryContext.getWatchDog());
// create a function call
try (final FunctionReference fnRef = new FunctionReference(new FunctionCall(xqueryContext, fn))) {
// convert the arguments
final org.exist.xquery.value.Sequence[] fnArgs = convertToExistFunctionArguments(xqueryContext, fn, arguments);
// execute the function call
fnRef.analyze(new AnalyzeContextInfo());
// if setUid/setGid, determine the effectiveSubject to use for execution
final Optional<EffectiveSubject> effectiveSubject = getEffectiveSubject(xquery);
try {
// switch to effective user if setUid/setGid
effectiveSubject.ifPresent(broker::pushSubject);
final org.exist.xquery.value.Sequence result = fnRef.evalFunction(null, null, fnArgs);
// copy for closure
final CompiledXQuery xquery1 = xquery;
// return a sequence adapter which returns the query when it is finished with the results
return new SequenceAdapter(result, () -> {
if (xquery1 != null) {
// return the compiled query to the pool
cache.returnCompiledQuery(resourceFunction.getXQueryLocation(), xquery1);
}
});
} finally {
// switch back from effective user if setUid/setGid
if (effectiveSubject.isPresent()) {
broker.popSubject();
}
}
}
} catch (final URISyntaxException | EXistException | XPathException | PermissionDeniedException use) {
// if an error occurred we should return the compiled query
if (xquery != null) {
// return the compiled query to the pool
cache.returnCompiledQuery(resourceFunction.getXQueryLocation(), xquery);
}
throw new RestXqServiceException(use.getMessage(), use);
} finally {
// clear down monitoring
if (processMonitor != null) {
xquery.getContext().getProfiler().traceQueryEnd(xquery.getContext());
processMonitor.queryCompleted(xquery.getContext().getWatchDog());
}
}
}
use of org.exist.security.EffectiveSubject in project exist by eXist-db.
the class XQuery method execute.
public Sequence execute(final DBBroker broker, final CompiledXQuery expression, Sequence contextSequence, final Properties outputProperties, final boolean resetContext) throws XPathException, PermissionDeniedException {
// check execute permissions
if (expression.getContext().getSource() instanceof DBSource) {
((DBSource) expression.getContext().getSource()).validate(Permission.EXECUTE);
}
final long start = System.currentTimeMillis();
final XQueryContext context = expression.getContext();
expression.reset();
if (resetContext) {
// context.setBroker(broker);
context.getWatchDog().reset();
}
if (context.requireDebugMode()) {
final Debuggee debuggee = broker.getBrokerPool().getDebuggee();
if (debuggee != null) {
debuggee.joint(expression);
}
}
// do any preparation before execution
context.prepareForExecution();
final Subject callingUser = broker.getCurrentSubject();
// if setUid or setGid, become Effective User
EffectiveSubject effectiveSubject = null;
final Source src = expression.getContext().getSource();
if (src instanceof DBSource) {
final DBSource dbSrc = (DBSource) src;
final Permission perm = dbSrc.getPermissions();
if (perm.isSetUid()) {
if (perm.isSetGid()) {
// setUid and SetGid
effectiveSubject = new EffectiveSubject(perm.getOwner(), perm.getGroup());
} else {
// just setUid
effectiveSubject = new EffectiveSubject(perm.getOwner());
}
} else if (perm.isSetGid()) {
// just setGid, so we use the current user as the effective user
effectiveSubject = new EffectiveSubject(callingUser, perm.getGroup());
}
}
try {
if (effectiveSubject != null) {
// switch to effective user (e.g. setuid/setgid)
broker.pushSubject(effectiveSubject);
}
context.getProfiler().traceQueryStart();
broker.getBrokerPool().getProcessMonitor().queryStarted(context.getWatchDog());
try {
// support for XQuery 3.0 - declare context item :=
if (contextSequence == null) {
if (context.getContextItemDeclartion() != null) {
contextSequence = context.getContextItemDeclartion().eval(null, null);
}
}
final Sequence result = expression.eval(contextSequence);
if (LOG.isDebugEnabled()) {
final NumberFormat nf = NumberFormat.getNumberInstance();
LOG.debug("Execution took {} ms", nf.format(System.currentTimeMillis() - start));
}
if (outputProperties != null) {
// must be done before context.reset!
context.checkOptions(outputProperties);
}
return result;
} finally {
context.getProfiler().traceQueryEnd(context);
// track query stats before context is reset
broker.getBrokerPool().getProcessMonitor().queryCompleted(context.getWatchDog());
expression.reset();
if (resetContext) {
context.reset();
}
}
} finally {
if (effectiveSubject != null) {
broker.popSubject();
}
}
}
Aggregations