summaryrefslogtreecommitdiffstats
blob: f2a36594185c7a6d697cd6f7e66598715e4a3d02 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * Copyright (c) 2010-2016 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#include <Limber/Server/ServerFromClientSession.h>

#include <memory>

#include <boost/bind.hpp>

#include <Swiften/Elements/AuthFailure.h>
#include <Swiften/Elements/AuthRequest.h>
#include <Swiften/Elements/AuthSuccess.h>
#include <Swiften/Elements/IQ.h>
#include <Swiften/Elements/ProtocolHeader.h>
#include <Swiften/Elements/ResourceBind.h>
#include <Swiften/Elements/StartSession.h>
#include <Swiften/Elements/StreamFeatures.h>
#include <Swiften/Network/Connection.h>
#include <Swiften/SASL/PLAINMessage.h>
#include <Swiften/StreamStack/XMPPLayer.h>

#include <Limber/Server/UserRegistry.h>

namespace Swift {

ServerFromClientSession::ServerFromClientSession(
        const std::string& id,
        std::shared_ptr<Connection> connection,
        PayloadParserFactoryCollection* payloadParserFactories,
        PayloadSerializerCollection* payloadSerializers,
        XMLParserFactory* xmlParserFactory,
        UserRegistry* userRegistry) :
            Session(connection, payloadParserFactories, payloadSerializers, xmlParserFactory),
            id_(id),
            userRegistry_(userRegistry),
            authenticated_(false),
            initialized(false),
            allowSASLEXTERNAL(false) {
}


void ServerFromClientSession::handleElement(std::shared_ptr<ToplevelElement> element) {
    if (isInitialized()) {
        onElementReceived(element);
    }
    else {
        if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
            if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
                if (authRequest->getMechanism() == "EXTERNAL") {
                        getXMPPLayer()->writeElement(std::make_shared<AuthSuccess>());
                        authenticated_ = true;
                        getXMPPLayer()->resetParser();
                }
                else {
                    PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : createSafeByteArray(""));
                    if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) {
                        getXMPPLayer()->writeElement(std::make_shared<AuthSuccess>());
                        user_ = plainMessage.getAuthenticationID();
                        authenticated_ = true;
                        getXMPPLayer()->resetParser();
                    }
                    else {
                        getXMPPLayer()->writeElement(std::shared_ptr<AuthFailure>(new AuthFailure));
                        finishSession(AuthenticationFailedError);
                    }
                }
            }
            else {
                getXMPPLayer()->writeElement(std::shared_ptr<AuthFailure>(new AuthFailure));
                finishSession(NoSupportedAuthMechanismsError);
            }
        }
        else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
            if (std::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
                setRemoteJID(JID(user_, getLocalJID().getDomain(), resourceBind->getResource()));
                std::shared_ptr<ResourceBind> resultResourceBind(new ResourceBind());
                resultResourceBind->setJID(getRemoteJID());
                getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind));
            }
            else if (iq->getPayload<StartSession>()) {
                getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID()));
                setInitialized();
            }
        }
    }
}

void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) {
    setLocalJID(JID("", incomingHeader.getTo()));
    ProtocolHeader header;
    header.setFrom(incomingHeader.getTo());
    header.setID(id_);
    getXMPPLayer()->writeHeader(header);

    std::shared_ptr<StreamFeatures> features(new StreamFeatures());
    if (!authenticated_) {
        features->addAuthenticationMechanism("PLAIN");
        if (allowSASLEXTERNAL) {
            features->addAuthenticationMechanism("EXTERNAL");
        }
    }
    else {
        features->setHasResourceBind();
        features->setHasSession();
    }
    getXMPPLayer()->writeElement(features);
}

void ServerFromClientSession::setInitialized() {
    initialized = true;
    onSessionStarted();
}

void ServerFromClientSession::setAllowSASLEXTERNAL() {
    allowSASLEXTERNAL = true;
}

}