280 WebdavResource *resource = op->response->addresource(op->response, href); |
280 WebdavResource *resource = op->response->addresource(op->response, href); |
281 if(!resource) { |
281 if(!resource) { |
282 return REQ_ABORTED; |
282 return REQ_ABORTED; |
283 } |
283 } |
284 |
284 |
|
285 // check ACL |
|
286 if(acl_evaluate(op->sn, op->rq, ACL_WRITE_XATTR)) { |
|
287 // ACL check failed, either unauthorized or forbidden |
|
288 // acl_evaluate() sets the http status code and may add |
|
289 // response headers for authentication |
|
290 if(op->rq->status_num == PROTOCOL_UNAUTHORIZED) { |
|
291 return REQ_ABORTED; // return here to send an authenticate response |
|
292 } |
|
293 |
|
294 // send multistatus response with status code 403 for each property |
|
295 log_ereport(LOG_VERBOSE, "webdav-proppatch: access forbidden"); |
|
296 int ret = REQ_PROCEED; |
|
297 WebdavPList *plist = op->proppatch->set; |
|
298 for(int i=0;i<2;i++) { |
|
299 while(plist) { |
|
300 if(resource->addproperty(resource, plist->property, PROTOCOL_FORBIDDEN)) { |
|
301 ret = REQ_ABORTED; |
|
302 break; // OOM |
|
303 } |
|
304 plist = plist->next; |
|
305 } |
|
306 plist = op->proppatch->remove; |
|
307 } |
|
308 |
|
309 if(resource->close(resource)) { |
|
310 ret = REQ_ABORTED; // OOM |
|
311 } |
|
312 return ret; |
|
313 } |
|
314 |
285 VFSContext *ctx = NULL; |
315 VFSContext *ctx = NULL; |
286 VFSFile *file = NULL; |
316 VFSFile *file = NULL; |
287 |
317 |
288 // requests for each backends |
318 // requests for each backends |
289 WebdavProppatchRequest **requests = pool_calloc( |
319 WebdavProppatchRequest **requests = pool_calloc( |