From 87745c0fde4041a6fb65135deabb2cf787b68574 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Latour Date: Fri, 4 Jan 2019 18:59:57 -0800 Subject: [PATCH] Use GCDWebServerNormalizePath() on all relative paths passed to GCDWebServer --- GCDWebDAVServer/GCDWebDAVServer.m | 46 +++++++++++-------------------- GCDWebServer/Core/GCDWebServer.m | 2 +- GCDWebUploader/GCDWebUploader.m | 39 +++++++++----------------- 3 files changed, 30 insertions(+), 57 deletions(-) diff --git a/GCDWebDAVServer/GCDWebDAVServer.m b/GCDWebDAVServer/GCDWebDAVServer.m index 1df6245..012d182 100644 --- a/GCDWebDAVServer/GCDWebDAVServer.m +++ b/GCDWebDAVServer/GCDWebDAVServer.m @@ -77,7 +77,7 @@ NS_ASSUME_NONNULL_END - (instancetype)initWithUploadDirectory:(NSString*)path { if ((self = [super init])) { - _uploadDirectory = [[path stringByStandardizingPath] copy]; + _uploadDirectory = [path copy]; GCDWebDAVServer* __unsafe_unretained server = self; // 9.1 PROPFIND method @@ -157,11 +157,6 @@ NS_ASSUME_NONNULL_END @implementation GCDWebDAVServer (Methods) -// Must match implementation in GCDWebUploader -- (BOOL)_checkSandboxedPath:(NSString*)path { - return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory]; -} - - (BOOL)_checkFileExtension:(NSString*)fileName { if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; @@ -186,9 +181,9 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { - (GCDWebServerResponse*)performGET:(GCDWebServerRequest*)request { NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -221,10 +216,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![self _checkSandboxedPath:absolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; - } + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory; if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath]; @@ -265,9 +257,9 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -299,10 +291,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![self _checkSandboxedPath:absolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; - } + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory; if (![[NSFileManager defaultManager] fileExistsAtPath:[absolutePath stringByDeletingLastPathComponent] isDirectory:&isDirectory] || !isDirectory) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Conflict message:@"Missing intermediate collection(s) for \"%@\"", relativePath]; @@ -348,10 +337,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { } NSString* srcRelativePath = request.path; - NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:srcRelativePath]; - if (![self _checkSandboxedPath:srcAbsolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; - } + NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(srcRelativePath)]; NSString* dstRelativePath = [request.headers objectForKey:@"Destination"]; NSRange range = [dstRelativePath rangeOfString:(NSString*)[request.headers objectForKey:@"Host"]]; @@ -362,8 +348,8 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { #pragma clang diagnostic ignored "-Wdeprecated-declarations" dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; #pragma clang diagnostic pop - NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:dstRelativePath]; - if (![self _checkSandboxedPath:dstAbsolutePath]) { + NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(dstRelativePath)]; + if (!dstAbsolutePath) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; } @@ -532,9 +518,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -582,9 +568,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -679,9 +665,9 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name } NSString* relativePath = request.path; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } diff --git a/GCDWebServer/Core/GCDWebServer.m b/GCDWebServer/Core/GCDWebServer.m index 481dbc4..c0f8b20 100644 --- a/GCDWebServer/Core/GCDWebServer.m +++ b/GCDWebServer/Core/GCDWebServer.m @@ -1026,7 +1026,7 @@ static inline NSString* _EncodeBase64(NSString* string) { } processBlock:^GCDWebServerResponse*(GCDWebServerRequest* request) { GCDWebServerResponse* response = nil; - NSString* filePath = [directoryPath stringByAppendingPathComponent:[request.path substringFromIndex:basePath.length]]; + NSString* filePath = [directoryPath stringByAppendingPathComponent:GCDWebServerNormalizePath([request.path substringFromIndex:basePath.length])]; NSString* fileType = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:NULL] fileType]; if (fileType) { if ([fileType isEqualToString:NSFileTypeDirectory]) { diff --git a/GCDWebUploader/GCDWebUploader.m b/GCDWebUploader/GCDWebUploader.m index 2ed00ed..9d166f1 100644 --- a/GCDWebUploader/GCDWebUploader.m +++ b/GCDWebUploader/GCDWebUploader.m @@ -37,6 +37,7 @@ #endif #import "GCDWebUploader.h" +#import "GCDWebServerFunctions.h" #import "GCDWebServerDataRequest.h" #import "GCDWebServerMultiPartFormRequest.h" @@ -73,7 +74,7 @@ NS_ASSUME_NONNULL_END if (siteBundle == nil) { return nil; } - _uploadDirectory = [[path stringByStandardizingPath] copy]; + _uploadDirectory = [path copy]; GCDWebUploader* __unsafe_unretained server = self; // Resource files @@ -192,11 +193,6 @@ NS_ASSUME_NONNULL_END @implementation GCDWebUploader (Methods) -// Must match implementation in GCDWebDAVServer -- (BOOL)_checkSandboxedPath:(NSString*)path { - return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory]; -} - - (BOOL)_checkFileExtension:(NSString*)fileName { if (_allowedFileExtensions && ![_allowedFileExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; @@ -224,9 +220,9 @@ NS_ASSUME_NONNULL_END - (GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request { NSString* relativePath = [[request query] objectForKey:@"path"]; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (!absolutePath || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } if (!isDirectory) { @@ -268,9 +264,9 @@ NS_ASSUME_NONNULL_END - (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request { NSString* relativePath = [[request query] objectForKey:@"path"]; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } if (isDirectory) { @@ -299,10 +295,7 @@ NS_ASSUME_NONNULL_END return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploaded file name \"%@\" is not allowed", file.fileName]; } NSString* relativePath = [[request firstArgumentForControlName:@"path"] string]; - NSString* absolutePath = [self _uniquePathForPath:[[_uploadDirectory stringByAppendingPathComponent:relativePath] stringByAppendingPathComponent:file.fileName]]; - if (![self _checkSandboxedPath:absolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; - } + NSString* absolutePath = [self _uniquePathForPath:[[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)] stringByAppendingPathComponent:file.fileName]]; if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath]; @@ -323,17 +316,14 @@ NS_ASSUME_NONNULL_END - (GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request { NSString* oldRelativePath = [request.arguments objectForKey:@"oldPath"]; - NSString* oldAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:oldRelativePath]; + NSString* oldAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(oldRelativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:oldAbsolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", oldRelativePath]; } NSString* newRelativePath = [request.arguments objectForKey:@"newPath"]; - NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:newRelativePath]]; - if (![self _checkSandboxedPath:newAbsolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", newRelativePath]; - } + NSString* newAbsolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(newRelativePath)]]; NSString* itemName = [newAbsolutePath lastPathComponent]; if ((!_allowHiddenItems && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { @@ -359,9 +349,9 @@ NS_ASSUME_NONNULL_END - (GCDWebServerResponse*)deleteItem:(GCDWebServerURLEncodedFormRequest*)request { NSString* relativePath = [request.arguments objectForKey:@"path"]; - NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; + NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]; BOOL isDirectory = NO; - if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -389,10 +379,7 @@ NS_ASSUME_NONNULL_END - (GCDWebServerResponse*)createDirectory:(GCDWebServerURLEncodedFormRequest*)request { NSString* relativePath = [request.arguments objectForKey:@"path"]; - NSString* absolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:relativePath]]; - if (![self _checkSandboxedPath:absolutePath]) { - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; - } + NSString* absolutePath = [self _uniquePathForPath:[_uploadDirectory stringByAppendingPathComponent:GCDWebServerNormalizePath(relativePath)]]; NSString* directoryName = [absolutePath lastPathComponent]; if (!_allowHiddenItems && [directoryName hasPrefix:@"."]) {