You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Joe Orton <jo...@orton.demon.co.uk> on 2000/07/24 03:19:44 UTC

[PATCH] mod_dav: authorization checking for Depth > 1

This adds full authorization checking for Depth > 1 requests as per the
mod_dav 1.1 tree.

joe

Index: fs/repos.c
===================================================================
RCS file: /home/joe/lib/cvsroot/apache2/src/modules/dav/fs/repos.c,v
retrieving revision 1.15
diff -u -p -r1.15 repos.c
--- repos.c	2000/07/15 02:07:21	1.15
+++ repos.c	2000/07/24 01:13:28
@@ -1316,10 +1316,9 @@ static dav_error * dav_fs_walker(dav_fs_
 	}
 
 	if (wctx->walk_type & DAV_WALKTYPE_AUTH) {
-	    /* ### need to authorize each file */
-	    /* ### example: .htaccess is normally configured to fail auth */
-
-	    /* stuff in the state directory is never authorized! */
+	    /* authorize properly after we have worked out the URI for
+	     * this resource: stuff in the state directory is never
+	     * authorized! */
 	    if (!strcmp(name, DAV_FS_STATE_DIR)) {
 		continue;
 	    }
@@ -1355,6 +1354,25 @@ static dav_error * dav_fs_walker(dav_fs_
 
 	/* set up the URI for the current resource */
 	fsctx->res1.uri = wctx->uri.buf;
+	
+	if (wctx->walk_type & DAV_WALKTYPE_AUTH) {
+	    request_rec *subr;
+	    
+	    /* check authorization for new resource, using apropriate method */
+	    subr = ap_sub_req_method_uri(wctx->r->method, wctx->uri.buf, wctx->r);
+	    /* we're only interested in the status */
+	    wctx->status = subr->status;
+	    ap_destroy_sub_req(subr);
+	    
+	    if (wctx->status != HTTP_OK) {
+		/* signal the error */
+		if ((err = (*wctx->func)(wctx, DAV_CALLTYPE_ERROR)) != NULL)
+		    return err;
+		
+		/* otherwise, skip to the next member resource */
+		continue;
+	    }
+	}
 
 	/* ### for now, only process regular files (e.g. skip symlinks) */
 	if (fsctx->info1.finfo.filetype == APR_REG) {
Index: main/mod_dav.c
===================================================================
RCS file: /home/joe/lib/cvsroot/apache2/src/modules/dav/main/mod_dav.c,v
retrieving revision 1.14
diff -u -p -r1.14 mod_dav.c
--- mod_dav.c	2000/07/17 05:17:02	1.14
+++ mod_dav.c	2000/07/24 01:13:50
@@ -1418,6 +1418,11 @@ static dav_error * dav_propfind_walker(d
     dav_propdb *propdb;
     dav_get_props_result propstats = { 0 };
 
+    if (calltype == DAV_CALLTYPE_ERROR) {
+	dav_add_response(ctx, ctx->uri.buf, ctx->status, NULL);
+	return NULL;
+    }
+
     /*
     ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
     ** dav_get_allprops() does not need to do namespace translation,
@@ -2176,29 +2181,29 @@ static int dav_method_copymove(request_r
     }
 
     /*
-    ** Check If-Headers and existing locks for each resource in the source
-    ** if we are performing a MOVE. We will return a 424 response with a
-    ** DAV:multistatus body. The multistatus responses will contain the
-    ** information about any resource that fails the validation.
+    ** Check If-Headers and existing locks for each resource in the source. 
+    ** We will return a 424 response with a DAV:multistatus body. The
+    ** multistatus responses will contain the information about any
+    ** resource that fails the validation.
     **
-    ** We check the parent resource, too, since this is a MOVE. Moving the
+    ** We check the parent resource, too, if this is a MOVE. Moving the
     ** resource effectively removes it from the parent collection, so we
     ** must ensure that we have met the appropriate conditions.
     **
     ** If a problem occurs with the Request-URI itself, then a plain error
     ** (rather than a multistatus) will be returned.
     */
-    if (is_move
-	&& (err = dav_validate_request(r, resource, depth, NULL,
-				       &multi_response,
-				       DAV_VALIDATE_PARENT
-                                       | DAV_VALIDATE_USE_424,
-                                       NULL)) != NULL) {
+    if ((err = dav_validate_request(r, resource, depth, NULL,
+				    &multi_response,
+				    (is_move?DAV_VALIDATE_PARENT:
+				     DAV_VALIDATE_READONLY)
+				    | DAV_VALIDATE_USE_424,
+				    NULL)) != NULL) {
 	err = dav_push_error(r->pool, err->status, 0,
 			     ap_psprintf(r->pool,
-					 "Could not MOVE %s due to a failed "
+					 "Could not %s %s due to a failed "
 					 "precondition on the source "
-					 "(e.g. locks).",
+					 "(e.g. locks).", r->method,
 					 ap_escape_html(r->pool, r->uri)),
 			     err);
 	return dav_handle_err(r, err, multi_response);
Index: main/mod_dav.h
===================================================================
RCS file: /home/joe/lib/cvsroot/apache2/src/modules/dav/main/mod_dav.h,v
retrieving revision 1.13
diff -u -p -r1.13 mod_dav.h
--- mod_dav.h	2000/07/10 07:49:48	1.13
+++ mod_dav.h	2000/07/24 01:13:54
@@ -843,6 +843,8 @@ dav_error * dav_validate_request(request
                                            the 424 DAV:response */
 #define DAV_VALIDATE_USE_424    0x0080  /* return 424 status, not 207 */
 #define DAV_VALIDATE_IS_PARENT  0x0100  /* for internal use */
+#define DAV_VALIDATE_READONLY   0x0200  /* validate for read access only 
+					   (e.g. source of COPY) */
 
 /* Lock-null related public lock functions */
 int dav_get_resource_state(request_rec *r, const dav_resource *resource);
@@ -1168,6 +1170,8 @@ typedef struct dav_walker_ctx
 #define DAV_CALLTYPE_COLLECTION	2	/* called for a collection */
 #define DAV_CALLTYPE_LOCKNULL	3	/* called for a locknull resource */
 #define DAV_CALLTYPE_POSTFIX	4	/* postfix call for a collection */
+#define DAV_CALLTYPE_ERROR	5	/* called for an error 
+					   (e.g. unauthorized) */
 
     ap_pool_t *pool;
 
@@ -1201,6 +1205,9 @@ typedef struct dav_walker_ctx
     int skip_root;			/* for dav_inherit_locks() */
 
     int flags;
+
+    /* the status-code for error calltype */
+    int status;
 
     dav_walker_private *info;           /* for use by repository manager */
 
Index: main/util.c
===================================================================
RCS file: /home/joe/lib/cvsroot/apache2/src/modules/dav/main/util.c,v
retrieving revision 1.5
diff -u -p -r1.5 util.c
--- util.c	2000/07/03 22:51:01	1.5
+++ util.c	2000/07/24 01:13:57
@@ -759,9 +759,12 @@ static dav_error * dav_validate_resource
 	** pretending that we've already met the requirement of seeing one
 	** of the resource's locks in the If: header.
 	**
+	** Ditto if we have only need read access to the resource.
+	**
 	** Otherwise, it must be cleared and we'll look for one.
 	*/
-        seen_locktoken = (lock_list == NULL);
+	seen_locktoken = (lock_list == NULL) ||
+	    ((flags & DAV_VALIDATE_READONLY) == DAV_VALIDATE_READONLY);
     }
 
     /*
@@ -1179,6 +1182,11 @@ static dav_error * dav_validate_walker(d
 {
     dav_error *err;
 
+    if (calltype == DAV_CALLTYPE_ERROR) {
+	dav_add_response(ctx, ctx->uri.buf, ctx->status, NULL);
+	return NULL;
+    }
+
     if ((err = dav_validate_resource_state(ctx->pool, ctx->resource,
 					   ctx->lockdb,
 					   ctx->if_header, ctx->flags,
@@ -1305,7 +1313,7 @@ dav_error * dav_validate_request(request
     if (resource->exists && depth > 0) {
 	dav_walker_ctx ctx = { 0 };
 
-	ctx.walk_type = DAV_WALKTYPE_ALL;
+	ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_AUTH;
 	ctx.postfix = 0;
 	ctx.func = dav_validate_walker;
 	ctx.pool = r->pool;
Index: main/util_lock.c
===================================================================
RCS file: /home/joe/lib/cvsroot/apache2/src/modules/dav/main/util_lock.c,v
retrieving revision 1.5
diff -u -p -r1.5 util_lock.c
--- util_lock.c	2000/07/07 10:38:23	1.5
+++ util_lock.c	2000/07/24 01:14:02
@@ -354,7 +354,7 @@ dav_error * dav_add_lock(request_rec *r,
 	/* Walk existing collection and set indirect locks */
 	dav_walker_ctx ctx = { 0 };
 
-	ctx.walk_type = DAV_WALKTYPE_ALL | DAV_WALKTYPE_AUTH;
+	ctx.walk_type = DAV_WALKTYPE_ALL;
 	ctx.postfix = 0;
 	ctx.func = dav_lock_walker;
 	ctx.pool = r->pool;