From 94f07eea7575ac3e92247cf16a907a6aa69fb75c Mon Sep 17 00:00:00 2001 From: Andrew McNab Date: Wed, 7 Sep 2005 09:38:51 +0000 Subject: [PATCH] Commit PUT/MOVE stuff --- org.gridsite.core/CHANGES | 6 ++ org.gridsite.core/doc/htcp.1 | 11 ++- org.gridsite.core/doc/htmv.1 | 1 + org.gridsite.core/doc/module.html | 6 ++ org.gridsite.core/src/gridsite.spec | 2 + org.gridsite.core/src/htcp | Bin 22680 -> 23556 bytes org.gridsite.core/src/htcp.c | 91 ++++++++++++++++++- org.gridsite.core/src/mod_gridsite.c | 169 ++++++++++++++++++++++++++++------- 8 files changed, 246 insertions(+), 40 deletions(-) create mode 100644 org.gridsite.core/doc/htmv.1 diff --git a/org.gridsite.core/CHANGES b/org.gridsite.core/CHANGES index 5a7716a..fc041b2 100644 --- a/org.gridsite.core/CHANGES +++ b/org.gridsite.core/CHANGES @@ -1,3 +1,9 @@ +* Fri Aug 26 2005 Andrew McNab +- Fix for HTTP PUT lack-of-truncation bug found by + Mike Jones, and support for HTTP/WebDAV MOVE. +- Add MOVE support to htcp and update htcp manpage. +- Unset CURLOPT_SSL_VERIFYPEER in htcp etc when using + --noverify option. * Fri Jun 10 2005 Andrew McNab - ==== GridSite version 1.1.11 ==== * Fri Jun 10 2005 Andrew McNab diff --git a/org.gridsite.core/doc/htcp.1 b/org.gridsite.core/doc/htcp.1 index 984aaaf..df4a07d 100644 --- a/org.gridsite.core/doc/htcp.1 +++ b/org.gridsite.core/doc/htcp.1 @@ -1,6 +1,6 @@ -.TH htcp 1 "July 2004" htcp "HTCP Manual" +.TH htcp 1 "September 2005" htcp "HTCP Manual" .SH NAME -.B htcp, htrm, htls, htll, htmkdir +.B htcp, htrm, htls, htll, htmkdir, htmv \- get, put, delete or list HTTP/HTTPS files or directories .SH SYNOPSIS .B htcp [options] @@ -53,6 +53,11 @@ with HTTP PUT. The server must support the convention that PUT to a URL with a trailing slash means create a directory. No file body is sent. Calling the program as htmkdir has the same effect. +.IP "--move" +Move/rename files on a single remote server, given the two, absolute URLs +of the remote file names. Server must support HTTP/WebDAV MOVE. Calling the +program as htmv has the same effect. + .IP "--anon" .br Do not attempt to use X.509 user certificates or GSI proxies to authenticate @@ -136,7 +141,7 @@ Recursive copying. Server-side wildcards. Parallel streams. Error recovery. Not enough beta testing (hint hint...) .SH AUTHOR -Andrew McNab +Andrew McNab htcp is part of GridSite: http://www.gridsite.org/ .SH "SEE ALSO" diff --git a/org.gridsite.core/doc/htmv.1 b/org.gridsite.core/doc/htmv.1 new file mode 100644 index 0000000..11a60d1 --- /dev/null +++ b/org.gridsite.core/doc/htmv.1 @@ -0,0 +1 @@ +.so man1/htcp.1 diff --git a/org.gridsite.core/doc/module.html b/org.gridsite.core/doc/module.html index 9cc97d4..f4a3acf 100644 --- a/org.gridsite.core/doc/module.html +++ b/org.gridsite.core/doc/module.html @@ -290,6 +290,12 @@ in effect. file being requested.

+

GRST_DESTINATION_TRANSLATED +
Present if a WebDAV Destination header was given in the request with a + local URL. Contains the translation of the URL given into an + absolute path in the local filesystem. +

+

GRST_HELP_URI
URI of website help pages set by GridSiteHelpURI directive.

diff --git a/org.gridsite.core/src/gridsite.spec b/org.gridsite.core/src/gridsite.spec index f55c349..badfdce 100644 --- a/org.gridsite.core/src/gridsite.spec +++ b/org.gridsite.core/src/gridsite.spec @@ -90,11 +90,13 @@ rm -f %(echo ${MYPREFIX:-/usr})/share/doc/gridsite %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htll %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htrm %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htmkdir +%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/bin/htmv %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htcp.1.gz %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htrm.1.gz %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htls.1.gz %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htll.1.gz %attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htmkdir.1.gz +%attr(-, root, root) %(echo ${MYPREFIX:-/usr})/share/man/man1/htmv.1.gz %files gsexec %attr(4510, root, apache) %(echo ${MYPREFIX:-/usr})/sbin/gsexec diff --git a/org.gridsite.core/src/htcp b/org.gridsite.core/src/htcp index 8a64842f5685ba9462ec46f27388593f059ae03f..f3d67c5b6397429fb306c7b76d41264c87f40e30 100644 GIT binary patch delta 8060 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 diff --git a/org.gridsite.core/src/htcp.c b/org.gridsite.core/src/htcp.c index 3275806..21b6c5b 100644 --- a/org.gridsite.core/src/htcp.c +++ b/org.gridsite.core/src/htcp.c @@ -1,5 +1,5 @@ /* - Copyright (c) 2002-4, Andrew McNab, University of Manchester + Copyright (c) 2002-5, Andrew McNab, University of Manchester All rights reserved. Redistribution and use in source and binary forms, with or @@ -72,6 +72,7 @@ #define HTCP_LIST 4 #define HTCP_LONGLIST 5 #define HTCP_MKDIR 6 +#define HTCP_MOVE 7 struct grst_stream_data { char *source; char *destination; @@ -200,8 +201,15 @@ int set_std_opts(CURL *easyhandle, struct grst_stream_data *common_data) } if (common_data->noverify) - curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 0); - else curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 2); + { + curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 0); + } + else + { + curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYPEER, 2); + curl_easy_setopt(easyhandle, CURLOPT_SSL_VERIFYHOST, 2); + } return 1; } @@ -448,6 +456,64 @@ int do_deletes(char *sources[], struct grst_stream_data *common_data) return anyerror; } +int do_move(char *source, char *destination, + struct grst_stream_data *common_data) +{ + int anyerror = 0, thiserror; + char *destination_header; + CURL *easyhandle; + struct grst_header_data header_data; + struct curl_slist *header_slist = NULL; + + easyhandle = curl_easy_init(); + + header_data.common_data = common_data; + + easyhandle = curl_easy_init(); + + asprintf(&destination_header, "Destination: %s", destination); + header_slist = curl_slist_append(header_slist, destination_header); + curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, header_slist); + + curl_easy_setopt(easyhandle, CURLOPT_USERAGENT, common_data->useragent); + if (common_data->verbose > 1) + curl_easy_setopt(easyhandle, CURLOPT_VERBOSE, 1); + + curl_easy_setopt(easyhandle, CURLOPT_HEADERFUNCTION, headers_callback); + curl_easy_setopt(easyhandle, CURLOPT_WRITEHEADER, &header_data); + + curl_easy_setopt(easyhandle, CURLOPT_ERRORBUFFER, common_data->errorbuf); + curl_easy_setopt(easyhandle, CURLOPT_CUSTOMREQUEST, "MOVE"); + curl_easy_setopt(easyhandle, CURLOPT_NOBODY, 1); + + set_std_opts(easyhandle, common_data); + + if (common_data->verbose > 0) + fprintf(stderr, "Moving %s to %s\n", source, destination); + + curl_easy_setopt(easyhandle, CURLOPT_URL, source); + + header_data.retcode = 0; + thiserror = curl_easy_perform(easyhandle); + + if ((thiserror != 0) || + (header_data.retcode < 200) || + (header_data.retcode >= 300)) + { + fprintf(stderr, "... curl error: %s (%d), HTTP error: %d\n", + common_data->errorbuf, thiserror, header_data.retcode); + + if (thiserror != 0) anyerror = thiserror; + else anyerror = header_data.retcode; + } + else if (common_data->verbose > 0) + fprintf(stderr, "... OK (%d)\n", header_data.retcode); + + curl_easy_cleanup(easyhandle); + + return anyerror; +} + int do_mkdirs(char *sources[], struct grst_stream_data *common_data) { int isrc, anyerror = 0, thiserror; @@ -988,6 +1054,7 @@ int main(int argc, char *argv[]) {"no-verify", 0, 0, 0}, {"anon", 0, 0, 0}, {"downgrade-size", 1, 0, 0}, + {"move", 0, 0, 0}, // {"streams", 1, 0, 0}, // {"blocksize", 1, 0, 0}, // {"recursive", 0, 0, 0}, @@ -1034,6 +1101,7 @@ int main(int argc, char *argv[]) else if (option_index == 8) common_data.noverify = 1; else if (option_index == 9) common_data.anonymous = 1; else if (option_index ==10) common_data.downgrade = atoll(optarg); + else if (option_index ==11) common_data.method = HTCP_MOVE; } else if (c == 'v') ++(common_data.verbose); } @@ -1115,6 +1183,7 @@ int main(int argc, char *argv[]) else if (strcmp(executable,"htll")==0) common_data.method=HTCP_LONGLIST; else if (strcmp(executable,"htrm")==0) common_data.method=HTCP_DELETE; else if (strcmp(executable,"htmkdir")==0) common_data.method=HTCP_MKDIR; + else if (strcmp(executable,"htmv")==0) common_data.method=HTCP_MOVE; } if ((common_data.method == HTCP_DELETE) || @@ -1159,6 +1228,22 @@ int main(int argc, char *argv[]) return anyerror; } + if (common_data.method == HTCP_MOVE) + { + if (optind >= argc - 1) + { + fputs("Must give exactly 2 non-option arguments\n\n", stderr); + printsyntax(argv[0]); + return CURLE_URL_MALFORMAT; + } + + anyerror = do_move(argv[optind], argv[optind + 1], &common_data); + + if (anyerror > 99) anyerror = CURLE_HTTP_RETURNED_ERROR; + + return anyerror; + } + if (optind >= argc - 1) { fputs("Must give at least 2 non-option arguments\n\n", stderr); diff --git a/org.gridsite.core/src/mod_gridsite.c b/org.gridsite.core/src/mod_gridsite.c index 450640f..7757c77 100644 --- a/org.gridsite.core/src/mod_gridsite.c +++ b/org.gridsite.core/src/mod_gridsite.c @@ -971,7 +971,8 @@ int http_put_method(request_rec *r, mod_gridsite_cfg *conf) /* *** otherwise assume trying to create a regular file *** */ - if (apr_file_open(&fp, r->filename, APR_WRITE | APR_CREATE | APR_BUFFERED, + if (apr_file_open(&fp, r->filename, + APR_WRITE | APR_CREATE | APR_BUFFERED | APR_TRUNCATE, conf->diskmode, r->pool) != 0) return HTTP_INTERNAL_SERVER_ERROR; /* we force the permissions, rather than accept any existing ones */ @@ -979,6 +980,7 @@ int http_put_method(request_rec *r, mod_gridsite_cfg *conf) apr_file_perms_set(r->filename, conf->diskmode); // TODO: need to add Range: support at some point too +// Also return 201 Created rather than 200 OK if not already existing retcode = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK); if (retcode == OK) @@ -1002,7 +1004,7 @@ int http_put_method(request_rec *r, mod_gridsite_cfg *conf) int http_delete_method(request_rec *r, mod_gridsite_cfg *conf) { - if (remove(r->filename) != 0) return HTTP_FORBIDDEN; + if (apr_file_remove(r->filename, r->pool) != 0) return HTTP_FORBIDDEN; ap_set_content_length(r, 0); ap_set_content_type(r, "text/html"); @@ -1010,6 +1012,24 @@ int http_delete_method(request_rec *r, mod_gridsite_cfg *conf) return OK; } +int http_move_method(request_rec *r, mod_gridsite_cfg *conf) +{ + char *destination_translated = NULL; + + if (r->notes != NULL) destination_translated = + (char *) apr_table_get(r->notes, "GRST_DESTINATION_TRANSLATED"); + + + if ((destination_translated == NULL) || + (apr_file_rename(r->filename, destination_translated, r->pool) != 0)) + return HTTP_FORBIDDEN; + + ap_set_content_length(r, 0); + ap_set_content_type(r, "text/html"); + + return OK; +} + static int mod_gridsite_dir_handler(request_rec *r, mod_gridsite_cfg *conf) /* handler switch for directories @@ -1074,6 +1094,11 @@ static int mod_gridsite_nondir_handler(request_rec *r, mod_gridsite_cfg *conf) (conf->methods != NULL) && (strstr(conf->methods, " DELETE ") != NULL)) return http_delete_method(r, conf); + + if ((r->method_number == M_MOVE) && + (conf->methods != NULL) && + (strstr(conf->methods, " MOVE ") != NULL)) + return http_move_method(r, conf); } /* *** check if a special ghost admin CGI *** */ @@ -1935,18 +1960,22 @@ static int mod_gridsite_perm_handler(request_rec *r) We also publish environment variables here if requested by GridSiteEnv. */ { - int retcode = DECLINED, i, n; + int retcode = DECLINED, i, n, file_is_acl = 0, + destination_is_acl = 0; char *dn, *p, envname[14], *grst_cred_0 = NULL, *dir_path, - *remotehost, s[99], *grst_cred_i, *file, *cookies, - *gridauthonetime, *cookiefile, oneline[1025], *key_i; + *remotehost, s[99], *grst_cred_i, *cookies, *file, + *gridauthonetime, *cookiefile, oneline[1025], *key_i, + *destination = NULL, *destination_uri = NULL, + *destination_prefix = NULL, *destination_translated = NULL; const char *content_type; time_t now, notbefore, notafter; apr_table_t *env; apr_finfo_t cookiefile_info; apr_file_t *fp; + request_rec *destreq; GRSTgaclCred *cred = NULL, *cred_0 = NULL; GRSTgaclUser *user = NULL; - GRSTgaclPerm perm = GRST_PERM_NONE; + GRSTgaclPerm perm = GRST_PERM_NONE, destination_perm = GRST_PERM_NONE; GRSTgaclAcl *acl = NULL; mod_gridsite_cfg *cfg; @@ -2094,26 +2123,93 @@ static int mod_gridsite_perm_handler(request_rec *r) if ((user != NULL) && ((mod_gridsite_cfg *) cfg)->dnlists) GRSTgaclUserSetDNlists(user, ((mod_gridsite_cfg *) cfg)->dnlists); - /* this checks for NULL arguments itself */ - if (GRSTgaclDNlistHasUser(((mod_gridsite_cfg *) cfg)->adminlist, user)) - perm = GRST_PERM_ALL; - else - { - remotehost = (char *) ap_get_remote_host(r->connection, + /* add DNS credential */ + + remotehost = (char *) ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_DOUBLE_REV, NULL); - if ((remotehost != NULL) && (*remotehost != '\0')) - { - cred = GRSTgaclCredNew("dns"); - GRSTgaclCredAddValue(cred, "hostname", remotehost); + if ((remotehost != NULL) && (*remotehost != '\0')) + { + cred = GRSTgaclCredNew("dns"); + GRSTgaclCredAddValue(cred, "hostname", remotehost); + + if (user == NULL) user = GRSTgaclUserNew(cred); + else GRSTgaclUserAddCred(user, cred); + } - if (user == NULL) user = GRSTgaclUserNew(cred); - else GRSTgaclUserAddCred(user, cred); + /* check for Destination: header and evaluate if present */ + + if ((destination = (char *) apr_table_get(r->headers_in, + "Destination")) != NULL) + { + destination_prefix = apr_psprintf(r->pool, "https://%s:%d/", + r->server->server_hostname, (int) r->server->port); + + if (strncmp(destination_prefix, destination, + strlen(destination_prefix)) == 0) + destination_uri = &destination[strlen(destination_prefix)-1]; + else if ((int) r->server->port == 443) + { + destination_prefix = apr_psprintf(r->pool, "https://%s/", + r->server->server_hostname); + + if (strncmp(destination_prefix, destination, + strlen(destination_prefix)) == 0) + destination_uri = &destination[strlen(destination_prefix)-1]; } + + if (destination_uri != NULL) + { + destreq = ap_sub_req_method_uri("GET", destination_uri, r, NULL); + + if ((destreq != NULL) && (destreq->filename != NULL) + && (destreq->path_info != NULL)) + { + destination_translated = apr_pstrcat(r->pool, + destreq->filename, destreq->path_info, NULL); + apr_table_setn(r->notes, "GRST_DESTINATION_TRANSLATED", + destination_translated); + + if (((mod_gridsite_cfg *) cfg)->envs) + apr_table_setn(env, "GRST_DESTINATION_TRANSLATED", + destination_translated); + + p = rindex(destination_translated, '/'); + if ((p != NULL) && (strcmp(&p[1], GRST_ACL_FILE) == 0)) + destination_is_acl = 1; + } + } + } + + /* this checks for NULL arguments itself */ + if (GRSTgaclDNlistHasUser(((mod_gridsite_cfg *) cfg)->adminlist, user)) + { + perm = GRST_PERM_ALL; + if (destination_translated != NULL) destination_perm = GRST_PERM_ALL; + } + else + { acl = GRSTgaclAclLoadforFile(r->filename); if (acl != NULL) perm = GRSTgaclAclTestUser(acl, user); - } + GRSTgaclAclFree(acl); + + if (destination_translated != NULL) + { + acl = GRSTgaclAclLoadforFile(destination_translated); + if (acl != NULL) destination_perm = GRSTgaclAclTestUser(acl, user); + GRSTgaclAclFree(acl); + apr_table_setn(r->notes, "GRST_DESTINATION_PERM", + apr_psprintf(r->pool, "%d", destination_perm)); + + if (((mod_gridsite_cfg *) cfg)->envs) + apr_table_setn(env, "GRST_DESTINATION_PERM", + apr_psprintf(r->pool, "%d", destination_perm)); + } + } + + /* set permission and GACL environment variables */ + apr_table_setn(r->notes, "GRST_PERM", apr_psprintf(r->pool, "%d", perm)); if (((mod_gridsite_cfg *) cfg)->envs) @@ -2207,13 +2303,9 @@ static int mod_gridsite_perm_handler(request_rec *r) { /* *** Check HTTP method to decide which perm bits to check *** */ - if (r->filename != NULL) - { - file = rindex(r->filename, '/'); - if (file != NULL) ++file; - else file = r->filename; - } - else file = NULL; + if ((r->filename != NULL) && + ((p = rindex(r->filename, '/')) != NULL) && + (strcmp(&p[1], GRST_ACL_FILE) == 0)) file_is_acl = 1; content_type = r->content_type; if ((content_type != NULL) && @@ -2248,14 +2340,23 @@ static int mod_gridsite_perm_handler(request_rec *r) ((r->method_number == M_POST) && !GRSTgaclPermHasRead(perm) ) || - (((r->method_number == M_PUT) || (r->method_number == M_DELETE)) && - !GRSTgaclPermHasWrite(perm) && - ((file == NULL) || (strcmp(file, GRST_ACL_FILE) != 0)) ) || - - (((r->method_number == M_PUT) || (r->method_number == M_DELETE)) && - !GRSTgaclPermHasAdmin(perm) && - (file != NULL) && - (strcmp(file, GRST_ACL_FILE) == 0) ) ) retcode = HTTP_FORBIDDEN; + (((r->method_number == M_PUT) || + (r->method_number == M_DELETE)) && + !GRSTgaclPermHasWrite(perm) && !file_is_acl) || + + ((r->method_number == M_MOVE) && + ((!GRSTgaclPermHasWrite(perm) && !file_is_acl) || + (!GRSTgaclPermHasAdmin(perm) && file_is_acl) || + (!GRSTgaclPermHasWrite(destination_perm) + && !destination_is_acl) || + (!GRSTgaclPermHasAdmin(destination_perm) + && destination_is_acl)) ) || + + (((r->method_number == M_PUT) || + (r->method_number == M_DELETE)) && + !GRSTgaclPermHasAdmin(perm) && file_is_acl) + + ) retcode = HTTP_FORBIDDEN; } return retcode; -- 1.8.2.3