feat(core): Allow disabling tls validation for localhost (#286)
parent
223b27b89b
commit
1f9888254a
|
@ -1832,6 +1832,9 @@ Supported formats are: `smtp://domain:port`, `smtps://domain`,
|
|||
`tls=YES` will enforce using STARTTLS smtp connections. Thus,
|
||||
`smtp://localhost:587/?tls=YES` would use the default MUA port
|
||||
on localhost with STARTTLS enforced.
|
||||
To disable TLS verification for localhost domains, passing
|
||||
`tlsVerifyMode=allowInsecureLocalhost` will such connections:
|
||||
`smtp://localhost:587/?tls=YES&tlsVerifyMode=allowInsecureLocalhost`.
|
||||
|
||||
|D |SOGoSMTPAuthenticationType
|
||||
|Activate SMTP authentication and specifies which type is in use.
|
||||
|
@ -1919,6 +1922,7 @@ URL with a fully qualified domain name, such as:
|
|||
[options="compact"]
|
||||
* `imaps://mail.acme.com:993`
|
||||
* `imap://mail.acme.com:143/?tls=YES`
|
||||
* `imap://127.0.0.1:143/?tls=YES&tlsVerifyMode=allowInsecureLocalhost`
|
||||
|
||||
|D |SOGoSieveServer
|
||||
|Parameter used to set the DNS name or IP address of the Sieve
|
||||
|
@ -1933,6 +1937,7 @@ qualified domain name, such as:
|
|||
|
||||
[options="compact"]
|
||||
* `sieve://mail.acme.com:4190/?tls=YES`
|
||||
* `sieve://127.0.0.14190/?tls=YES&tlsVerifyMode=allowInsecureLocalhost`
|
||||
|
||||
Note that TLS is supported but SSL is not.
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
SOGoMailAccount
|
||||
Parent object: SOGoMailAccounts
|
||||
Child objects: SOGoMailFolder
|
||||
|
||||
|
||||
The SOGoMailAccount represents a single IMAP4 mail account (host, login,
|
||||
password, etc)
|
||||
*/
|
||||
|
@ -91,6 +91,7 @@ typedef enum {
|
|||
- (NSDictionary *) identityForEmail: (NSString *) email;
|
||||
- (NSString *) signature;
|
||||
- (NSString *) encryption;
|
||||
- (NSString *) tlsVerifyMode;
|
||||
|
||||
/* folder pathes */
|
||||
- (NSArray *) toManyRelationshipKeysWithNamespaces: (BOOL) withNSs;
|
||||
|
|
|
@ -92,7 +92,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
[otherUsersFolderName release];
|
||||
[sharedFoldersName release];
|
||||
[subscribedFolders release];
|
||||
[super dealloc];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL) isInDraftsFolder
|
||||
|
@ -135,7 +135,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
if (namespace)
|
||||
{
|
||||
[self _appendNamespace: namespace toFolders: folders];
|
||||
ASSIGN(otherUsersFolderName, [folders lastObject]);
|
||||
ASSIGN(otherUsersFolderName, [folders lastObject]);
|
||||
}
|
||||
|
||||
namespace = [namespaceDict objectForKey: @"shared"];
|
||||
|
@ -275,7 +275,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
SOGoDomainDefaults *dd;
|
||||
id inboxQuota, infos;
|
||||
float quota;
|
||||
|
||||
|
||||
inboxQuota = nil;
|
||||
if ([self supportsQuotas])
|
||||
{
|
||||
|
@ -744,6 +744,17 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
return encryption;
|
||||
}
|
||||
|
||||
- (NSString *) tlsVerifyMode
|
||||
{
|
||||
NSString *verifyMode;
|
||||
|
||||
verifyMode = [[self _mailAccount] objectForKey: @"tlsVerifyMode"];
|
||||
if (!verifyMode || ![verifyMode length])
|
||||
verifyMode = @"default";
|
||||
|
||||
return verifyMode;
|
||||
}
|
||||
|
||||
- (NSMutableString *) imap4URLString
|
||||
{
|
||||
NSMutableString *imap4URLString;
|
||||
|
@ -829,7 +840,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
NSEnumerator *e;
|
||||
NSString *guid;
|
||||
id currentFolder;
|
||||
|
||||
|
||||
BOOL hasAnnotatemore;
|
||||
|
||||
ud = [[context activeUser] userDefaults];
|
||||
|
@ -854,7 +865,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
result = [client annotation: @"*" entryName: @"/comment" attributeName: @"value.priv"];
|
||||
else
|
||||
result = [client lstatus: @"*" flags: [NSArray arrayWithObjects: @"x-guid", nil]];
|
||||
|
||||
|
||||
e = [folderList objectEnumerator];
|
||||
|
||||
while ((currentFolder = [[e nextObject] substringFromIndex: 1]))
|
||||
|
@ -863,7 +874,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
guid = [[[[result objectForKey: @"FolderList"] objectForKey: currentFolder] objectForKey: @"/comment"] objectForKey: @"value.priv"];
|
||||
else
|
||||
guid = [[[result objectForKey: @"status"] objectForKey: currentFolder] objectForKey: @"x-guid"];
|
||||
|
||||
|
||||
if (!guid || ![guid isNotNull])
|
||||
{
|
||||
// Don't generate a GUID for "Other users" and "Shared" namespace folders - user foldername instead
|
||||
|
@ -881,7 +892,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
guid = [NSString stringWithFormat: @"%@", currentFolder];
|
||||
else
|
||||
{
|
||||
// If folder doesn't exists - ignore it.
|
||||
// If folder doesn't exists - ignore it.
|
||||
nresult = [client status: currentFolder
|
||||
flags: [NSArray arrayWithObject: @"UIDVALIDITY"]];
|
||||
if (![[nresult valueForKey: @"result"] boolValue])
|
||||
|
@ -897,10 +908,10 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
guid = [NSString stringWithFormat: @"%@", currentFolder];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[folders setObject: [NSString stringWithFormat: @"folder%@", guid] forKey: [NSString stringWithFormat: @"folder%@", currentFolder]];
|
||||
}
|
||||
|
||||
|
||||
return folders;
|
||||
}
|
||||
|
||||
|
@ -964,7 +975,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
}
|
||||
else
|
||||
obj = [super lookupName: _key inContext: _ctx acquire: NO];
|
||||
|
||||
|
||||
/* return 404 to stop acquisition */
|
||||
if (!obj)
|
||||
obj = [NSException exceptionWithHTTPStatus: 404 /* Not Found */];
|
||||
|
@ -1224,7 +1235,7 @@ static NSString *inboxFolderName = @"INBOX";
|
|||
if (delegateUser)
|
||||
[delegateUser removeMailDelegator: owner];
|
||||
}
|
||||
|
||||
|
||||
[self _setDelegates: delegates];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
container];
|
||||
folder = nil;
|
||||
}
|
||||
|
||||
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
@ -211,7 +211,7 @@
|
|||
// use the container's one.
|
||||
//
|
||||
login = [[[self context] activeUser] login];
|
||||
|
||||
|
||||
if (!login)
|
||||
login = [[[[self container] context] activeUser] login];
|
||||
|
||||
|
@ -265,7 +265,7 @@
|
|||
[self warnWithFormat:@"container does not implement -imap4URL!"];
|
||||
url = nil;
|
||||
}
|
||||
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
@ -285,6 +285,7 @@
|
|||
{
|
||||
SOGoMailAccount *account;
|
||||
NSString *urlString;
|
||||
NSString *useTls = @"NO";
|
||||
|
||||
/* this could probably be handled better from NSURL but it's buggy in
|
||||
GNUstep */
|
||||
|
@ -292,10 +293,11 @@
|
|||
{
|
||||
account = [self mailAccountFolder];
|
||||
if ([[account encryption] isEqualToString: @"tls"])
|
||||
urlString = [NSString stringWithFormat: @"%@?tls=YES",
|
||||
[self imap4URLString]];
|
||||
else
|
||||
urlString = [self imap4URLString];
|
||||
{
|
||||
useTls = @"YES";
|
||||
}
|
||||
urlString = [NSString stringWithFormat: @"%@?tls=%@&tlsVerifyMode=%@",
|
||||
[self imap4URLString], useTls, [account tlsVerifyMode]];
|
||||
imap4URL = [[NSURL alloc] initWithString: urlString];
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#import <NGObjWeb/WOContext.h>
|
||||
#import <NGObjWeb/WORequest.h>
|
||||
#import <NGExtensions/NSCalendarDate+misc.h>
|
||||
#import <NGExtensions/NSURL+misc.h>
|
||||
#import <NGExtensions/NSNull+misc.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
|
@ -136,7 +137,7 @@
|
|||
|
||||
_defaults = nil;
|
||||
_settings = nil;
|
||||
|
||||
|
||||
uid = nil;
|
||||
realUID = nil;
|
||||
domain = nil;
|
||||
|
@ -166,7 +167,7 @@
|
|||
domain = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newLogin = [newLogin stringByReplacingString: @"%40"
|
||||
withString: @"@"];
|
||||
if (b)
|
||||
|
@ -312,7 +313,7 @@
|
|||
return allEmails;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// We always return the last object among our list of email addresses. This value
|
||||
// is always added in SOGoUserManager: -_fillContactMailRecords:
|
||||
//
|
||||
|
@ -396,7 +397,7 @@
|
|||
format = [ud timeFormat];
|
||||
if (format)
|
||||
[dateFormatter setTimeFormat: format];
|
||||
|
||||
|
||||
return dateFormatter;
|
||||
}
|
||||
|
||||
|
@ -475,7 +476,7 @@
|
|||
|
||||
- (SOGoUserSettings *) userSettings
|
||||
{
|
||||
if (!_settings)
|
||||
if (!_settings)
|
||||
{
|
||||
_settings = [SOGoUserSettings settingsForUser: login];
|
||||
[_settings retain];
|
||||
|
@ -643,8 +644,9 @@
|
|||
- (void) _appendSystemMailAccountWithDelegatedIdentities: (BOOL) appendDeletegatedIdentities
|
||||
{
|
||||
NSString *fullName, *imapLogin, *imapServer, *cImapServer,
|
||||
*encryption, *scheme, *action, *query, *customEmail, *sieveServer;
|
||||
*encryption, *scheme, *action, *queryTls, *customEmail, *sieveServer, *tlsVerifyMode;
|
||||
NSMutableDictionary *mailAccount, *identity, *mailboxes, *receipts, *security, *mailSettings;
|
||||
NSDictionary *queryComponents;
|
||||
NSNumber *port;
|
||||
NSMutableArray *identities, *mails;
|
||||
NSArray *delegators, *delegates;
|
||||
|
@ -692,36 +694,43 @@
|
|||
|
||||
// 3. port & encryption
|
||||
scheme = [cUrl scheme] ? [cUrl scheme] : [url scheme];
|
||||
query = [cUrl query] ? [cUrl query] : [url query];
|
||||
|
||||
queryComponents = [cUrl query] ? [cUrl queryComponents] : [url queryComponents];
|
||||
queryTls = [queryComponents valueForKey: @"tls"];
|
||||
tlsVerifyMode = [queryComponents valueForKey: @"tlsVerifyMode"];
|
||||
|
||||
if (!tlsVerifyMode)
|
||||
tlsVerifyMode = @"default";
|
||||
|
||||
if (scheme
|
||||
&& [scheme caseInsensitiveCompare: @"imaps"] == NSOrderedSame)
|
||||
{
|
||||
if (query && [query caseInsensitiveCompare: @"tls=YES"] == NSOrderedSame)
|
||||
{
|
||||
defaultPort = 143;
|
||||
encryption = @"tls";
|
||||
}
|
||||
if (queryTls && [queryTls caseInsensitiveCompare: @"YES"] == NSOrderedSame)
|
||||
{
|
||||
defaultPort = 143;
|
||||
encryption = @"tls";
|
||||
}
|
||||
else
|
||||
{
|
||||
encryption = @"ssl";
|
||||
defaultPort = 993;
|
||||
}
|
||||
{
|
||||
encryption = @"ssl";
|
||||
defaultPort = 993;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (query && [query caseInsensitiveCompare: @"tls=YES"] == NSOrderedSame)
|
||||
if (queryTls && [queryTls caseInsensitiveCompare: @"YES"] == NSOrderedSame)
|
||||
encryption = @"tls";
|
||||
else
|
||||
encryption = @"none";
|
||||
|
||||
|
||||
defaultPort = 143;
|
||||
}
|
||||
|
||||
port = [cUrl port] ? [cUrl port] : [url port];
|
||||
if ([port intValue] == 0) /* port is nil or intValue == 0 */
|
||||
port = [NSNumber numberWithInt: defaultPort];
|
||||
[mailAccount setObject: port forKey: @"port"];
|
||||
[mailAccount setObject: encryption forKey: @"encryption"];
|
||||
[mailAccount setObject: tlsVerifyMode forKey: @"tlsVerifyMode"];
|
||||
|
||||
// 4. Sieve server
|
||||
sieveServer = [self _fetchFieldForUser: @"c_sievehostname"];
|
||||
|
@ -730,7 +739,7 @@
|
|||
{
|
||||
[mailAccount setObject: sieveServer forKey: @"sieveServerName"];
|
||||
}
|
||||
|
||||
|
||||
// 5. Identities
|
||||
identities = [NSMutableArray new];
|
||||
[identities addObjectsFromArray: [_defaults mailIdentities]];
|
||||
|
@ -1048,11 +1057,11 @@
|
|||
- (SOGoContactFolder *) personalContactsFolderInContext: (WOContext *) context
|
||||
{
|
||||
SOGoContactFolders *folders;
|
||||
|
||||
|
||||
folders = [[self homeFolderInContext: context] lookupName: @"Contacts"
|
||||
inContext: context
|
||||
acquire: NO];
|
||||
|
||||
|
||||
return [folders lookupPersonalFolder: @"personal"
|
||||
ignoringRights: YES];
|
||||
}
|
||||
|
@ -1113,7 +1122,7 @@
|
|||
id authValue;
|
||||
|
||||
authValue = [self _fetchFieldForUser: @"canAuthenticate"];
|
||||
|
||||
|
||||
return [authValue boolValue];
|
||||
}
|
||||
|
||||
|
@ -1158,9 +1167,9 @@
|
|||
- (int) numberOfSimultaneousBookings
|
||||
{
|
||||
NSNumber *v;
|
||||
|
||||
|
||||
v = [self _fetchFieldForUser: @"numberOfSimultaneousBookings"];
|
||||
|
||||
|
||||
if (v)
|
||||
return [v intValue];
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ $(TEST_TOOL)_OBJC_FILES += \
|
|||
TestNSString+Crypto.m \
|
||||
TestNSString+URLEscaping.m \
|
||||
TestNSString+Utilities.m \
|
||||
TestNSURL+misc.m \
|
||||
TestNGMailAddressParser.m \
|
||||
TestNGInternetSocketAddress.m \
|
||||
\
|
||||
# I don't know how to link against -l:SOGoBackend \
|
||||
undefined reference to `__objc_class_name_SOGoMailFolder'
|
||||
|
@ -42,7 +44,7 @@ $(TEST_TOOL)_CPPFLAGS += \
|
|||
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
-L../../SoObjects/SOGo/SOGo.framework/Versions/Current/sogo -L../../SOPE/NGCards/obj -L../../SOPE/GDLContentStore/obj -lSOGo -lNGMime -lNGCards -lGDLContentStore -lNGExtensions -lSBJson -lobjc \
|
||||
-L/usr/local/lib -lSaxObjC \
|
||||
-L/usr/local/lib -lSaxObjC -lNGStreams \
|
||||
-Wl,-rpath,../../SoObjects/SOGo/SOGo.framework/Versions/Current/sogo -Wl,-rpath,../../SOPE/NGCards/obj -Wl,-rpath,../../SOPE/GDLContentStore/obj
|
||||
ADDITIONAL_LDFLAGS += -Wl,--no-as-needed
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* TestNGInternetSocketAddress.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2020 Nicolas Höft
|
||||
*
|
||||
* Author: Nicolas Höft <nicolas@hoeft.de>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <NGStreams/NGInternetSocketAddress.h>
|
||||
|
||||
#import "SOGoTest.h"
|
||||
|
||||
@interface TestNGInternetSocketAddress : SOGoTest
|
||||
@end
|
||||
|
||||
@implementation TestNGInternetSocketAddress
|
||||
|
||||
- (void) test_isLocalhost
|
||||
{
|
||||
// @"localhost6",
|
||||
NSString *addrStr[] = { @"127.0.0.1", @"127.1.2.3", @"localhost", @"something.localhost", @"localhost.", nil };
|
||||
NSString **curHost;
|
||||
BOOL is_localhost;
|
||||
NSString *error;
|
||||
|
||||
curHost = addrStr;
|
||||
while (*curHost)
|
||||
{
|
||||
NGInternetSocketAddress *addr;
|
||||
addr = [NGInternetSocketAddress addressWithPort: 1234
|
||||
onHost: *curHost];
|
||||
is_localhost = [addr isLocalhost];
|
||||
|
||||
error = [NSString stringWithFormat:
|
||||
@"expected '%@' to be a localhost address", *curHost];
|
||||
testWithMessage(is_localhost, error);
|
||||
|
||||
curHost++;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -61,10 +61,6 @@
|
|||
[NSNumber numberWithInt: NSISOLatin1StringEncoding],
|
||||
[NSNumber numberWithInt: 0],
|
||||
|
||||
@"nil",
|
||||
[NSNumber numberWithInt: [NSString defaultCStringEncoding]],
|
||||
[NSNumber numberWithInt: 0],
|
||||
|
||||
@"",
|
||||
[NSNumber numberWithInt: [NSString defaultCStringEncoding]],
|
||||
[NSNumber numberWithInt: 0],
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/* TestNSURL+miscm - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2020 Nicolas Höft
|
||||
*
|
||||
* Author: Nicolas Höft <nicolas@hoeft.de>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#import <Foundation/NSDictionary.h>
|
||||
|
||||
#import <NGStreams/NGInternetSocketAddress.h>
|
||||
#import <NGExtensions/NSURL+misc.h>
|
||||
|
||||
#import "SOGoTest.h"
|
||||
|
||||
@interface TestNSURL_plusmisc : SOGoTest
|
||||
@end
|
||||
|
||||
@implementation TestNSURL_plusmisc
|
||||
|
||||
- (void) test_queryComponents
|
||||
{
|
||||
NSString *urlStr;
|
||||
NSString *error;
|
||||
NSURL *url;
|
||||
NSDictionary *queryComp;
|
||||
|
||||
urlStr = @"http://domain/path?key=value";
|
||||
|
||||
url = [NSURL URLWithString: urlStr];
|
||||
queryComp = [url queryComponents];
|
||||
|
||||
error = [NSString stringWithFormat:
|
||||
@"expected '%@' to have 1 entry", urlStr];
|
||||
testWithMessage([queryComp count] == 1, error);
|
||||
|
||||
test([[queryComp valueForKey: @"key"] isEqualToString: @"value"]);
|
||||
|
||||
urlStr = @"http://domain/path?key1=value123&key2=val2&";
|
||||
url = [NSURL URLWithString: urlStr];
|
||||
queryComp = [url queryComponents];
|
||||
error = [NSString stringWithFormat:
|
||||
@"expected '%@' to have 2 entries, got %d", urlStr, [queryComp count]];
|
||||
testWithMessage([queryComp count] == 2, error);
|
||||
|
||||
test([[queryComp valueForKey: @"key1"] isEqualToString: @"value123"]);
|
||||
test([[queryComp valueForKey: @"key2"] isEqualToString: @"val2"]);
|
||||
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in New Issue