Add support for anonymous authentication

This commit is contained in:
Jonathan Schleifer 2018-11-11 13:17:03 +01:00
parent d76fc4129d
commit b1c3f82596
No known key found for this signature in database
GPG key ID: D83A76BFE376345E
5 changed files with 127 additions and 41 deletions

View file

@ -6,7 +6,8 @@ FRAMEWORK = ${OBJXMPP_FRAMEWORK}
LIB_MAJOR = 0 LIB_MAJOR = 0
LIB_MINOR = 0 LIB_MINOR = 0
SRCS = XMPPAuthenticator.m \ SRCS = XMPPANONYMOUSAuth.m \
XMPPAuthenticator.m \
XMPPCallback.m \ XMPPCallback.m \
XMPPConnection.m \ XMPPConnection.m \
XMPPContact.m \ XMPPContact.m \

35
src/XMPPANONYMOUSAuth.h Normal file
View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018, Jonathan Schleifer <js@heap.zone>
*
* https://heap.zone/objxmpp/
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#import <ObjFW/ObjFW.h>
#import "XMPPAuthenticator.h"
OF_ASSUME_NONNULL_BEGIN
/*!
* @brief A class to authenticate using SASL ANONYMOUS.
*/
@interface XMPPANONYMOUSAuth: XMPPAuthenticator
@end
OF_ASSUME_NONNULL_END

28
src/XMPPANONYMOUSAuth.m Normal file
View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2018, Jonathan Schleifer <js@heap.zone>
*
* https://heap.zone/objxmpp/
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice is present in all copies.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#import "XMPPANONYMOUSAuth.h"
@implementation XMPPANONYMOUSAuth: XMPPAuthenticator
@end

View file

@ -147,109 +147,113 @@ OF_ASSUME_NONNULL_BEGIN
OF_KINDOF(OFTCPSocket *) _socket; OF_KINDOF(OFTCPSocket *) _socket;
OFXMLParser *_parser, *_oldParser; OFXMLParser *_parser, *_oldParser;
OFXMLElementBuilder *_elementBuilder, *_oldElementBuilder; OFXMLElementBuilder *_elementBuilder, *_oldElementBuilder;
OFString *_username, *_password, *_server, *_resource; OFString *_Nullable _username, *_Nullable _password, *_Nullable _server;
OFString *_privateKeyFile, *_certificateFile; OFString *_Nullable _resource;
const char *_privateKeyPassphrase; bool _usesAnonymousAuthentication;
OFString *_domain, *_domainToASCII; OFString *_Nullable _privateKeyFile, *_Nullable _certificateFile;
XMPPJID *_JID; const char *_Nullable _privateKeyPassphrase;
OFString *_Nullable _domain, *_Nullable _domainToASCII;
XMPPJID *_Nullable _JID;
uint16_t _port; uint16_t _port;
id <XMPPStorage> _dataStorage; id <XMPPStorage> _Nullable _dataStorage;
OFString *_language; OFString *_Nullable _language;
XMPPMulticastDelegate *_delegates; XMPPMulticastDelegate *_delegates;
OFMutableDictionary OF_GENERIC(OFString *, XMPPCallback *) *_callbacks; OFMutableDictionary OF_GENERIC(OFString *, XMPPCallback *) *_callbacks;
XMPPAuthenticator *_authModule; XMPPAuthenticator *_authModule;
bool _streamOpen; bool _streamOpen, _needsSession, _encryptionRequired, _encrypted;
bool _needsSession; bool _supportsRosterVersioning, _supportsStreamManagement;
bool _encryptionRequired, _encrypted;
bool _supportsRosterVersioning;
bool _supportsStreamManagement;
unsigned int _lastID; unsigned int _lastID;
} }
/*! /*!
* The username to use for authentication. * @brief The username to use for authentication.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *username; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *username;
/*! /*!
* The password to use for authentication. * @brief The password to use for authentication.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *password; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *password;
/*! /*!
* The server to use for the connection. * @brief The server to use for the connection.
* *
* This is useful if the address of the server is different from the domain. * This is useful if the address of the server is different from the domain.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *server; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *server;
/*! /*!
* The domain to connect to. * @brief The domain to connect to.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *domain; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *domain;
/*! /*!
* The resource to request for the connection. * @brief The resource to request for the connection.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *resource; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *resource;
/*! /*!
* The language to request for the connection. * @brief Whether the connection uses SASL ANONYMOUS authentication.
*/
@property (nonatomic) bool usesAnonymousAuthentication;
/*!
* @brief The language to request for the connection.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *language; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *language;
/*! /*!
* A private key file to use for authentication. * @brief A private key file to use for authentication.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *privateKeyFile; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *privateKeyFile;
/*! /*!
* A certificate file to use for authentication. * @brief A certificate file to use for authentication.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *certificateFile; @property OF_NULLABLE_PROPERTY (nonatomic, copy) OFString *certificateFile;
/*! /*!
* The JID the server assigned to the connection after binding. * @brief The JID the server assigned to the connection after binding.
*/ */
@property (readonly, nonatomic) XMPPJID *JID; @property OF_NULLABLE_PROPERTY (readonly, nonatomic) XMPPJID *JID;
/*! /*!
* The port to connect to. * @brief The port to connect to.
*/ */
@property (nonatomic) uint16_t port; @property (nonatomic) uint16_t port;
/*! /*!
* An object for data storage, conforming to the XMPPStorage protocol. * @brief An object for data storage, conforming to the XMPPStorage protocol.
*/ */
@property OF_NULLABLE_PROPERTY (nonatomic, assign) id <XMPPStorage> dataStorage; @property OF_NULLABLE_PROPERTY (nonatomic, assign) id <XMPPStorage> dataStorage;
/*! /*!
* The socket used for the connection. * @brief The socket used for the connection.
*/ */
@property (readonly, nonatomic) OF_KINDOF(OFTCPSocket *) socket; @property (readonly, nonatomic) OF_KINDOF(OFTCPSocket *) socket;
/*! /*!
* Whether encryption is required. * @brief Whether encryption is required.
*/ */
@property (nonatomic) bool encryptionRequired; @property (nonatomic) bool encryptionRequired;
/*! /*!
* Whether the connection is encrypted. * @brief Whether the connection is encrypted.
*/ */
@property (readonly, nonatomic) bool encrypted; @property (readonly, nonatomic) bool encrypted;
/*! /*!
* Whether roster versioning is supported. * @brief Whether roster versioning is supported.
*/ */
@property (readonly, nonatomic) bool supportsRosterVersioning; @property (readonly, nonatomic) bool supportsRosterVersioning;
/*! /*!
* Whether stream management is supported. * @brief Whether stream management is supported.
*/ */
@property (readonly, nonatomic) bool supportsStreamManagement; @property (readonly, nonatomic) bool supportsStreamManagement;
/*! /*!
* Creates a new autoreleased XMPPConnection. * @brief Creates a new autoreleased XMPPConnection.
* *
* @return A new autoreleased XMPPConnection * @return A new autoreleased XMPPConnection
*/ */

View file

@ -38,18 +38,20 @@
#import <ObjFW/OFInvalidArgumentException.h> #import <ObjFW/OFInvalidArgumentException.h>
#import "XMPPConnection.h" #import "XMPPConnection.h"
#import "XMPPANONYMOUSAuth.h"
#import "XMPPCallback.h" #import "XMPPCallback.h"
#import "XMPPEXTERNALAuth.h" #import "XMPPEXTERNALAuth.h"
#import "XMPPSCRAMAuth.h"
#import "XMPPPLAINAuth.h"
#import "XMPPStanza.h"
#import "XMPPJID.h"
#import "XMPPIQ.h"
#import "XMPPMessage.h"
#import "XMPPPresence.h"
#import "XMPPMulticastDelegate.h"
#import "XMPPExceptions.h" #import "XMPPExceptions.h"
#import "XMPPIQ.h"
#import "XMPPJID.h"
#import "XMPPMessage.h"
#import "XMPPMulticastDelegate.h"
#import "XMPPPLAINAuth.h"
#import "XMPPPresence.h"
#import "XMPPSCRAMAuth.h"
#import "XMPPStanza.h"
#import "XMPPXMLElementBuilder.h" #import "XMPPXMLElementBuilder.h"
#import "namespaces.h" #import "namespaces.h"
#import <ObjFW/macros.h> #import <ObjFW/macros.h>
@ -99,6 +101,7 @@
@implementation XMPPConnection @implementation XMPPConnection
@synthesize username = _username, resource = _resource, server = _server; @synthesize username = _username, resource = _resource, server = _server;
@synthesize domain = _domain, password = _password, JID = _JID, port = _port; @synthesize domain = _domain, password = _password, JID = _JID, port = _port;
@synthesize usesAnonymousAuthentication = _usesAnonymousAuthentication;
@synthesize language = _language, privateKeyFile = _privateKeyFile; @synthesize language = _language, privateKeyFile = _privateKeyFile;
@synthesize certificateFile = _certificateFile, socket = _socket; @synthesize certificateFile = _certificateFile, socket = _socket;
@synthesize encryptionRequired = _encryptionRequired, encrypted = _encrypted; @synthesize encryptionRequired = _encryptionRequired, encrypted = _encrypted;
@ -1014,6 +1017,18 @@
for (OFXMLElement *mech in [mechs children]) for (OFXMLElement *mech in [mechs children])
[mechanisms addObject: [mech stringValue]]; [mechanisms addObject: [mech stringValue]];
if (_usesAnonymousAuthentication) {
if (![mechanisms containsObject: @"ANONYMOUS"])
@throw [XMPPAuthFailedException
exceptionWithConnection: self
reason: @"No supported "
@"auth mechanism"];
_authModule = [[XMPPANONYMOUSAuth alloc] init];
[self xmpp_sendAuth: @"ANONYMOUS"];
return;
}
if (_privateKeyFile != nil && _certificateFile != nil && if (_privateKeyFile != nil && _certificateFile != nil &&
[mechanisms containsObject: @"EXTERNAL"]) { [mechanisms containsObject: @"EXTERNAL"]) {
_authModule = [[XMPPEXTERNALAuth alloc] init]; _authModule = [[XMPPEXTERNALAuth alloc] init];
@ -1051,7 +1066,10 @@
return; return;
} }
assert(0); @throw [XMPPAuthFailedException
exceptionWithConnection: self
reason: @"No supported auth mechanism"];
} }
if (session != nil && [session elementForName: @"optional" if (session != nil && [session elementForName: @"optional"
@ -1075,7 +1093,7 @@
namespace: XMPP_NS_SASL]; namespace: XMPP_NS_SASL];
[authTag addAttributeWithName: @"mechanism" [authTag addAttributeWithName: @"mechanism"
stringValue: authName]; stringValue: authName];
if (initialMessage) { if (initialMessage != nil) {
if ([initialMessage count] == 0) if ([initialMessage count] == 0)
[authTag setStringValue: @"="]; [authTag setStringValue: @"="];
else else