diff --git a/GCDWebDAVServer/GCDWebDAVServer.m b/GCDWebDAVServer/GCDWebDAVServer.m index afbd86f..4b51762 100644 --- a/GCDWebDAVServer/GCDWebDAVServer.m +++ b/GCDWebDAVServer/GCDWebDAVServer.m @@ -61,6 +61,11 @@ typedef NS_ENUM(NSInteger, DAVProperties) { @implementation GCDWebDAVServer (Methods) +// Must match implementation in GCDWebUploader +- (BOOL)_checkSandboxedPath:(NSString*)path { + return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory]; +} + - (BOOL)_checkFileExtension:(NSString*)fileName { if (_allowedExtensions && ![_allowedExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; @@ -87,7 +92,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -116,7 +121,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![absolutePath hasPrefix:_uploadDirectory]) { + if (![self _checkSandboxedPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } BOOL isDirectory; @@ -161,7 +166,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -194,7 +199,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - if (![absolutePath hasPrefix:_uploadDirectory]) { + if (![self _checkSandboxedPath:absolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } BOOL isDirectory; @@ -243,7 +248,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { NSString* srcRelativePath = request.path; NSString* srcAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:srcRelativePath]; - if (![srcAbsolutePath hasPrefix:_uploadDirectory]) { + if (![self _checkSandboxedPath:srcAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; } @@ -254,7 +259,7 @@ static inline BOOL _IsMacFinder(GCDWebServerRequest* request) { } dstRelativePath = [[dstRelativePath substringFromIndex:(range.location + range.length)] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSString* dstAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:dstRelativePath]; - if (![dstAbsolutePath hasPrefix:_uploadDirectory]) { + if (![self _checkSandboxedPath:dstAbsolutePath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", srcRelativePath]; } @@ -425,7 +430,7 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -475,7 +480,7 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -575,7 +580,7 @@ static inline xmlNodePtr _XMLChildWithName(xmlNodePtr child, const xmlChar* name NSString* relativePath = request.path; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![absolutePath hasPrefix:_uploadDirectory] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } diff --git a/GCDWebUploader/GCDWebUploader.m b/GCDWebUploader/GCDWebUploader.m index 56eb6da..4c76fd3 100644 --- a/GCDWebUploader/GCDWebUploader.m +++ b/GCDWebUploader/GCDWebUploader.m @@ -57,6 +57,11 @@ @implementation GCDWebUploader (Methods) +// Must match implementation in GCDWebDAVServer +- (BOOL)_checkSandboxedPath:(NSString*)path { + return [[path stringByStandardizingPath] hasPrefix:_uploadDirectory]; +} + - (BOOL)_checkFileExtension:(NSString*)fileName { if (_allowedExtensions && ![_allowedExtensions containsObject:[[fileName pathExtension] lowercaseString]]) { return NO; @@ -85,8 +90,8 @@ - (GCDWebServerResponse*)listDirectory:(GCDWebServerRequest*)request { NSString* relativePath = [[request query] objectForKey:@"path"]; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - BOOL isDirectory; - if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + BOOL isDirectory = NO; + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } if (!isDirectory) { @@ -129,8 +134,8 @@ - (GCDWebServerResponse*)downloadFile:(GCDWebServerRequest*)request { NSString* relativePath = [[request query] objectForKey:@"path"]; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; - BOOL isDirectory; - if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + BOOL isDirectory = NO; + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } if (isDirectory) { @@ -160,6 +165,9 @@ } 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]; + } if (![self shouldUploadFileAtPath:absolutePath withTemporaryFile:file.temporaryPath]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_Forbidden message:@"Uploading file \"%@\" to \"%@\" is not permitted", file.fileName, relativePath]; @@ -181,13 +189,16 @@ - (GCDWebServerResponse*)moveItem:(GCDWebServerURLEncodedFormRequest*)request { NSString* oldRelativePath = [request.arguments objectForKey:@"oldPath"]; NSString* oldAbsolutePath = [_uploadDirectory stringByAppendingPathComponent:oldRelativePath]; - BOOL isDirectory; - if (![[NSFileManager defaultManager] fileExistsAtPath:oldAbsolutePath isDirectory:&isDirectory]) { + BOOL isDirectory = NO; + if (![self _checkSandboxedPath:oldAbsolutePath] || ![[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* itemName = [newAbsolutePath lastPathComponent]; if ((!_allowHidden && [itemName hasPrefix:@"."]) || (!isDirectory && ![self _checkFileExtension:itemName])) { @@ -215,7 +226,7 @@ NSString* relativePath = [request.arguments objectForKey:@"path"]; NSString* absolutePath = [_uploadDirectory stringByAppendingPathComponent:relativePath]; BOOL isDirectory = NO; - if (![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { + if (![self _checkSandboxedPath:absolutePath] || ![[NSFileManager defaultManager] fileExistsAtPath:absolutePath isDirectory:&isDirectory]) { return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_NotFound message:@"\"%@\" does not exist", relativePath]; } @@ -244,6 +255,9 @@ - (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* directoryName = [absolutePath lastPathComponent]; if (!_allowHidden && [directoryName hasPrefix:@"."]) {