~ubuntu-branches/ubuntu/karmic/psi/karmic

« back to all changes in this revision

Viewing changes to third-party/qca/qca-cyrus-sasl/qca-cyrus-sasl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * qca-sasl.cpp - SASL plugin for QCA
 
3
 * Copyright (C) 2003-2007  Justin Karneges <justin@affinix.com>
 
4
 * Copyright (C) 2006  Michail Pishchagin <mblsha@gmail.com>
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2.1 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General Public
 
17
 * License along with this library; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
19
 *
 
20
 */
 
21
 
 
22
#include <QtCrypto>
 
23
#include <QDebug>
 
24
#include <QtCore/qplugin.h>
 
25
 
 
26
extern "C"
 
27
{
 
28
#include <sasl/sasl.h>
 
29
}
 
30
 
 
31
#include <QHostAddress>
 
32
#include <QStringList>
 
33
#include <QList>
 
34
#include <QFile>
 
35
 
 
36
#define SASL_BUFSIZE 8192
 
37
#define SASL_APP     "qca"
 
38
 
 
39
using namespace QCA;
 
40
 
 
41
namespace saslQCAPlugin {
 
42
 
 
43
class saslProvider : public Provider
 
44
{
 
45
public:
 
46
        saslProvider();
 
47
        void init();
 
48
        ~saslProvider();
 
49
        int qcaVersion() const;
 
50
        QString name() const;
 
51
        QString credit() const;
 
52
        QStringList features() const;
 
53
        Context *createContext(const QString &type);
 
54
 
 
55
        bool client_init;
 
56
        bool server_init;
 
57
        QString appname;
 
58
};
 
59
 
 
60
//----------------------------------------------------------------------------
 
61
// SASLParams
 
62
//----------------------------------------------------------------------------
 
63
 
 
64
class SASLParams
 
65
{
 
66
public:
 
67
        class SParams
 
68
        {
 
69
        public:
 
70
                bool user, authzid, pass, realm;
 
71
        };
 
72
 
 
73
        SASLParams()
 
74
        {
 
75
                reset();
 
76
        }
 
77
 
 
78
        void reset()
 
79
        {
 
80
                resetNeed();
 
81
                resetHave();
 
82
                foreach(char *result, results)
 
83
                        delete result;
 
84
                results.clear();
 
85
        }
 
86
 
 
87
        void resetNeed()
 
88
        {
 
89
                need.user = false;
 
90
                need.authzid = false;
 
91
                need.pass = false;
 
92
                need.realm = false;
 
93
        }
 
94
 
 
95
        void resetHave()
 
96
        {
 
97
                have.user = false;
 
98
                have.authzid = false;
 
99
                have.pass = false;
 
100
                have.realm = false;
 
101
        }
 
102
 
 
103
        void setUsername(const QString &s)
 
104
        {
 
105
                have.user = true;
 
106
                user = s;
 
107
        }
 
108
 
 
109
        void setAuthzid(const QString &s)
 
110
        {
 
111
                have.authzid = true;
 
112
                authzid = s;
 
113
        }
 
114
 
 
115
        void setPassword(const SecureArray &s)
 
116
        {
 
117
                have.pass = true;
 
118
                pass = QString::fromUtf8(s.toByteArray());
 
119
        }
 
120
 
 
121
        void setRealm(const QString &s)
 
122
        {
 
123
                have.realm = true;
 
124
                realm = s;
 
125
        }
 
126
 
 
127
        void applyInteract(sasl_interact_t *needp)
 
128
        {
 
129
                for(int n = 0; needp[n].id != SASL_CB_LIST_END; ++n) {
 
130
                        if(needp[n].id == SASL_CB_AUTHNAME)
 
131
                                need.user = true;       // yes, I know these
 
132
                        if(needp[n].id == SASL_CB_USER)
 
133
                                need.authzid = true;    // look backwards
 
134
                        if(needp[n].id == SASL_CB_PASS)
 
135
                                need.pass = true;
 
136
                        if(needp[n].id == SASL_CB_GETREALM)
 
137
                                need.realm = true;
 
138
                }
 
139
        }
 
140
 
 
141
        void extractHave(sasl_interact_t *needp)
 
142
        {
 
143
                for(int n = 0; needp[n].id != SASL_CB_LIST_END; ++n) {
 
144
                        if(needp[n].id == SASL_CB_AUTHNAME && have.user)
 
145
                                setValue(&needp[n], user);
 
146
                        if(needp[n].id == SASL_CB_USER && have.authzid)
 
147
                                setValue(&needp[n], authzid);
 
148
                        if(needp[n].id == SASL_CB_PASS && have.pass)
 
149
                                setValue(&needp[n], pass);
 
150
                        if(needp[n].id == SASL_CB_GETREALM && have.realm)
 
151
                                setValue(&needp[n], realm);
 
152
                }
 
153
        }
 
154
 
 
155
        bool missingAny() const
 
156
        {
 
157
                if((need.user && !have.user) /*|| (need.authzid && !have.authzid)*/ || (need.pass && !have.pass) /*|| (need.realm && !have.realm)*/)
 
158
                        return true;
 
159
                return false;
 
160
        }
 
161
 
 
162
        SParams missing() const
 
163
        {
 
164
                SParams np = need;
 
165
                if(have.user)
 
166
                        np.user = false;
 
167
                if(have.authzid)
 
168
                        np.authzid = false;
 
169
                if(have.pass)
 
170
                        np.pass = false;
 
171
                if(have.realm)
 
172
                        np.realm = false;
 
173
                return np;
 
174
        }
 
175
 
 
176
        void setValue(sasl_interact_t *i, const QString &s)
 
177
        {
 
178
                if(i->result)
 
179
                        return;
 
180
                QByteArray cs = s.toUtf8();
 
181
                int len = cs.length();
 
182
                char *p = new char[len+1];
 
183
                memcpy(p, cs.data(), len);
 
184
                p[len] = 0;
 
185
                i->result = p;
 
186
                i->len = len;
 
187
 
 
188
                // record this
 
189
                results.append(p);
 
190
        }
 
191
 
 
192
        QList<char *> results;
 
193
        SParams need;
 
194
        SParams have;
 
195
        QString user, authzid, pass, realm;
 
196
};
 
197
 
 
198
static QByteArray makeByteArray(const void *in, unsigned int len)
 
199
{
 
200
        QByteArray buf(len, 0);
 
201
        memcpy(buf.data(), in, len);
 
202
        return buf;
 
203
}
 
204
 
 
205
static QString addrString(const SASLContext::HostPort &hp)
 
206
{
 
207
        return (hp.addr + ';' + QString::number(hp.port));
 
208
}
 
209
 
 
210
//----------------------------------------------------------------------------
 
211
// saslContext
 
212
//----------------------------------------------------------------------------
 
213
 
 
214
class saslContext : public SASLContext
 
215
{
 
216
        saslProvider *g;
 
217
 
 
218
        // core props
 
219
        QString service, host;
 
220
        QString localAddr, remoteAddr;
 
221
 
 
222
        // security props
 
223
        int secflags;
 
224
        int ssf_min, ssf_max;
 
225
        QString ext_authid;
 
226
        int ext_ssf;
 
227
 
 
228
        sasl_conn_t *con;
 
229
        sasl_interact_t *need;
 
230
        int maxoutbuf;
 
231
        sasl_callback_t *callbacks;
 
232
 
 
233
        // state
 
234
        bool servermode;
 
235
        int step;
 
236
        bool in_sendFirst;
 
237
        QByteArray in_buf;
 
238
        QString in_mech;
 
239
        bool in_useClientInit;
 
240
        QByteArray in_clientInit;
 
241
        QString out_mech;
 
242
        // bool out_useClientInit;
 
243
        // QByteArray out_clientInit;
 
244
        QByteArray out_buf;
 
245
 
 
246
        SASLParams params;
 
247
        QString sc_username, sc_authzid;
 
248
        bool ca_flag, ca_done, ca_skip;
 
249
        int last_r;
 
250
 
 
251
        int result_ssf;
 
252
        Result result_result;
 
253
        bool result_haveClientInit;
 
254
        QStringList result_mechlist;
 
255
        SASL::AuthCondition result_authCondition;
 
256
        QByteArray result_to_net;
 
257
        QByteArray result_plain;
 
258
 
 
259
private:
 
260
        void resetState()
 
261
        {
 
262
                if(con) {
 
263
                        sasl_dispose(&con);
 
264
                        con = 0;
 
265
                }
 
266
                need = 0;
 
267
                if(callbacks) {
 
268
                        delete callbacks;
 
269
                        callbacks = 0;
 
270
                }
 
271
 
 
272
                localAddr = "";
 
273
                remoteAddr = "";
 
274
                maxoutbuf = 128;
 
275
                sc_username = "";
 
276
                sc_authzid = "";
 
277
 
 
278
                result_authCondition = SASL::AuthFail;
 
279
                result_haveClientInit = false;
 
280
                result_mechlist.clear();
 
281
                result_plain.clear();
 
282
                result_plain.clear();
 
283
                result_plain.clear();
 
284
                result_ssf = 0;
 
285
        }
 
286
 
 
287
        void resetParams()
 
288
        {
 
289
                params.reset();
 
290
                secflags = 0;
 
291
                ssf_min = 0;
 
292
                ssf_max = 0;
 
293
                ext_authid = "";
 
294
                ext_ssf = 0;
 
295
        }
 
296
 
 
297
        bool setsecprops()
 
298
        {
 
299
                sasl_security_properties_t secprops;
 
300
                secprops.min_ssf = ssf_min;
 
301
                secprops.max_ssf = ssf_max;
 
302
                secprops.maxbufsize = SASL_BUFSIZE;
 
303
                secprops.property_names = NULL;
 
304
                secprops.property_values = NULL;
 
305
                secprops.security_flags = secflags;
 
306
                int r = sasl_setprop(con, SASL_SEC_PROPS, &secprops);
 
307
                if(r != SASL_OK)
 
308
                        return false;
 
309
 
 
310
                if(!ext_authid.isEmpty()) {
 
311
                        const char *authid = ext_authid.toLatin1().data();
 
312
                        sasl_ssf_t ssf = ext_ssf;
 
313
                        r = sasl_setprop(con, SASL_SSF_EXTERNAL, &ssf);
 
314
                        if(r != SASL_OK)
 
315
                                return false;
 
316
                        r = sasl_setprop(con, SASL_AUTH_EXTERNAL, &authid);
 
317
                        if(r != SASL_OK)
 
318
                                return false;
 
319
                }
 
320
 
 
321
                return true;
 
322
        }
 
323
 
 
324
        void setAuthCondition(int r)
 
325
        {
 
326
            //qDebug() << "authcondition: " << r;
 
327
                SASL::AuthCondition x;
 
328
                switch(r) {
 
329
                        // common
 
330
                        case SASL_NOMECH:    x = SASL::NoMechanism; break;
 
331
                        case SASL_BADPROT:   x = SASL::BadProtocol; break;
 
332
 
 
333
                        // client
 
334
                        case SASL_BADSERV:   x = SASL::BadServer; break;
 
335
 
 
336
                        // server
 
337
                        case SASL_BADAUTH:   x = SASL::BadAuth; break;
 
338
                        case SASL_NOAUTHZ:   x = SASL::NoAuthzid; break;
 
339
                        case SASL_TOOWEAK:   x = SASL::TooWeak; break;
 
340
                        case SASL_ENCRYPT:   x = SASL::NeedEncrypt; break;
 
341
                        case SASL_EXPIRED:   x = SASL::Expired; break;
 
342
                        case SASL_DISABLED:  x = SASL::Disabled; break;
 
343
                        case SASL_NOUSER:    x = SASL::NoUser; break;
 
344
                        case SASL_UNAVAIL:   x = SASL::RemoteUnavailable; break;
 
345
 
 
346
                        default: x = SASL::AuthFail; break;
 
347
                }
 
348
                result_authCondition = x;
 
349
        }
 
350
 
 
351
        void getssfparams()
 
352
        {
 
353
                const void *maybe_sff;
 
354
                if( SASL_OK == sasl_getprop( con, SASL_SSF, &maybe_sff ) )
 
355
                        result_ssf = *(const int*)maybe_sff;
 
356
 
 
357
                const void *maybe_maxoutbuf;
 
358
                if (SASL_OK == sasl_getprop( con, SASL_MAXOUTBUF, &maybe_maxoutbuf ) )
 
359
                        maxoutbuf = *(const int*)maybe_maxoutbuf;
 
360
        }
 
361
 
 
362
        static int scb_checkauth(sasl_conn_t *, void *context, const char *requested_user, unsigned, const char *auth_identity, unsigned, const char *, unsigned, struct propctx *)
 
363
        {
 
364
                saslContext *that = (saslContext *)context;
 
365
                that->sc_username = auth_identity; // yeah yeah, it looks
 
366
                that->sc_authzid = requested_user; // backwards, but it is right
 
367
                that->ca_flag = true;
 
368
                return SASL_OK;
 
369
        }
 
370
 
 
371
        void clientTryAgain()
 
372
        {
 
373
                result_haveClientInit = false;
 
374
 
 
375
                if(step == 0) {
 
376
                        const char *clientout, *m;
 
377
                        unsigned int clientoutlen;
 
378
 
 
379
                        need = 0;
 
380
                        QString list = result_mechlist.join(" ");
 
381
                        int r;
 
382
                        while(1) {
 
383
                                if(need)
 
384
                                        params.extractHave(need);
 
385
                                if(in_sendFirst)
 
386
                                        r = sasl_client_start(con, list.toLatin1().data(), &need, &clientout, &clientoutlen, &m);
 
387
                                else
 
388
                                        r = sasl_client_start(con, list.toLatin1().data(), &need, NULL, NULL, &m);
 
389
                                if(r != SASL_INTERACT)
 
390
                                        break;
 
391
 
 
392
                                params.applyInteract(need);
 
393
                                if(params.missingAny()) {
 
394
                                        result_result = Params;
 
395
                                        return;
 
396
                                }
 
397
                        }
 
398
                        if(r != SASL_OK && r != SASL_CONTINUE) {
 
399
                                setAuthCondition(r);
 
400
                                result_result = Error;
 
401
                                return;
 
402
                        }
 
403
 
 
404
                        out_mech = m;
 
405
                        if(in_sendFirst && clientout) {
 
406
                                out_buf = makeByteArray(clientout, clientoutlen);
 
407
                                result_haveClientInit = true;
 
408
                        }
 
409
 
 
410
                        ++step;
 
411
 
 
412
                        if(r == SASL_OK) {
 
413
                                getssfparams();
 
414
                                result_result = Success;
 
415
                                return;
 
416
                        }
 
417
                        result_result = Continue;
 
418
                        return;
 
419
                }
 
420
                else {
 
421
                        const char *clientout;
 
422
                        unsigned int clientoutlen;
 
423
                        int r;
 
424
                        while(1) {
 
425
                                if(need)
 
426
                                        params.extractHave(need);
 
427
                                //printf("sasl_client_step(con, {%s}, %d, &need, &clientout, &clientoutlen);\n", in_buf.data(), in_buf.size());
 
428
                                r = sasl_client_step(con, in_buf.data(), in_buf.size(), &need, &clientout, &clientoutlen);
 
429
                                //printf("returned: %d\n", r);
 
430
                                if(r != SASL_INTERACT)
 
431
                                        break;
 
432
 
 
433
                                params.applyInteract(need);
 
434
                                if(params.missingAny()) {
 
435
                                        result_result = Params;
 
436
                                        return;
 
437
                                }
 
438
                        }
 
439
                        if(r != SASL_OK && r != SASL_CONTINUE) {
 
440
                                setAuthCondition(r);
 
441
                                result_result = Error;
 
442
                                return;
 
443
                        }
 
444
                        out_buf = makeByteArray(clientout, clientoutlen);
 
445
                        if(r == SASL_OK) {
 
446
                                getssfparams();
 
447
                                result_result = Success;
 
448
                                return;
 
449
                        }
 
450
                        result_result = Continue;
 
451
                        return;
 
452
                }
 
453
        }
 
454
 
 
455
        void serverTryAgain()
 
456
        {
 
457
                if(step == 0) {
 
458
                        if(!ca_skip) {
 
459
                                const char *clientin = 0;
 
460
                                unsigned int clientinlen = 0;
 
461
                                if(in_useClientInit) {
 
462
                                        clientin = in_clientInit.data();
 
463
                                        clientinlen = in_clientInit.size();
 
464
                                }
 
465
                                const char *serverout;
 
466
                                unsigned int serveroutlen;
 
467
                                ca_flag = false;
 
468
                                int r = sasl_server_start(con, in_mech.toLatin1().data(), clientin, clientinlen, &serverout, &serveroutlen);
 
469
                                if(r != SASL_OK && r != SASL_CONTINUE) {
 
470
                                        setAuthCondition(r);
 
471
                                        result_result = Error;
 
472
                                        return;
 
473
                                }
 
474
                                out_buf = makeByteArray(serverout, serveroutlen);
 
475
                                last_r = r;
 
476
                                if(ca_flag && !ca_done) {
 
477
                                        ca_done = true;
 
478
                                        ca_skip = true;
 
479
                                        result_result = AuthCheck;
 
480
                                        return;
 
481
                                }
 
482
                        }
 
483
                        ca_skip = false;
 
484
                        ++step;
 
485
 
 
486
                        if(last_r == SASL_OK) {
 
487
                                getssfparams();
 
488
                                result_result = Success;
 
489
                                return;
 
490
                        }
 
491
                        result_result = Continue;
 
492
                        return;
 
493
                }
 
494
                else {
 
495
                        if(!ca_skip) {
 
496
                                const char *serverout;
 
497
                                unsigned int serveroutlen;
 
498
                                int r = sasl_server_step(con, in_buf.data(), in_buf.size(), &serverout, &serveroutlen);
 
499
                                if(r != SASL_OK && r != SASL_CONTINUE) {
 
500
                                        setAuthCondition(r);
 
501
                                        result_result = Error;
 
502
                                        return;
 
503
                                }
 
504
                                if(r == SASL_OK)
 
505
                                        out_buf.resize(0);
 
506
                                else
 
507
                                        out_buf = makeByteArray(serverout, serveroutlen);
 
508
                                last_r = r;
 
509
                                if(ca_flag && !ca_done) {
 
510
                                        ca_done = true;
 
511
                                        ca_skip = true;
 
512
                                        result_result = AuthCheck;
 
513
                                        return;
 
514
                                }
 
515
                        }
 
516
                        ca_skip = false;
 
517
                        if(last_r == SASL_OK) {
 
518
                                getssfparams();
 
519
                                result_result = Success;
 
520
                                return;
 
521
                        }
 
522
                        result_result = Continue;
 
523
                        return;
 
524
                }
 
525
        }
 
526
 
 
527
        bool sasl_endecode(const QByteArray &in, QByteArray *out, bool enc)
 
528
        {
 
529
                // no security
 
530
                if(result_ssf == 0) {
 
531
                        *out = in;
 
532
                        return true;
 
533
                }
 
534
 
 
535
                int at = 0;
 
536
                out->resize(0);
 
537
                while(1) {
 
538
                        int size = in.size() - at;
 
539
                        if(size == 0)
 
540
                                break;
 
541
                        if(size > maxoutbuf)
 
542
                                size = maxoutbuf;
 
543
                        const char *outbuf;
 
544
                        unsigned len;
 
545
                        int r;
 
546
                        if(enc)
 
547
                                r = sasl_encode(con, in.data() + at, size, &outbuf, &len);
 
548
                        else
 
549
                                r = sasl_decode(con, in.data() + at, size, &outbuf, &len);
 
550
                        if(r != SASL_OK)
 
551
                                return false;
 
552
                        int oldsize = out->size();
 
553
                        out->resize(oldsize + len);
 
554
                        memcpy(out->data() + oldsize, outbuf, len);
 
555
                        at += size;
 
556
                }
 
557
                return true;
 
558
        }
 
559
 
 
560
        void doResultsReady()
 
561
        {
 
562
                QMetaObject::invokeMethod(this, "resultsReady", Qt::QueuedConnection);
 
563
        }
 
564
 
 
565
public:
 
566
        saslContext(saslProvider *_g)
 
567
        : SASLContext(_g)
 
568
        {
 
569
                result_result = Success;
 
570
                g = _g;
 
571
                con = 0;
 
572
                callbacks = 0;
 
573
 
 
574
                reset();
 
575
        }
 
576
 
 
577
        ~saslContext()
 
578
        {
 
579
                reset();
 
580
        }
 
581
 
 
582
        virtual Provider::Context *clone() const
 
583
        {
 
584
                return 0;
 
585
        }
 
586
 
 
587
        virtual Result result() const
 
588
        {
 
589
                return result_result;
 
590
        }
 
591
 
 
592
        virtual void reset()
 
593
        {
 
594
                resetState();
 
595
                resetParams();
 
596
        }
 
597
 
 
598
        virtual void setup(const QString &_service, const QString &_host, const HostPort *local, const HostPort *remote, const QString &ext_id, int _ext_ssf)
 
599
        {
 
600
                service = _service;
 
601
                host = _host;
 
602
                localAddr = local ? addrString(*local) : "";
 
603
                remoteAddr = remote ? addrString(*remote) : "";
 
604
                ext_authid = ext_id;
 
605
                ext_ssf = _ext_ssf;
 
606
        }
 
607
 
 
608
        virtual int ssf() const
 
609
        {
 
610
                return result_ssf;
 
611
        }
 
612
 
 
613
        virtual void startClient(const QStringList &mechlist, bool allowClientSendFirst)
 
614
        {
 
615
                resetState();
 
616
 
 
617
                in_sendFirst = allowClientSendFirst;
 
618
 
 
619
                if(!g->client_init) {
 
620
                        sasl_client_init(NULL);
 
621
                        g->client_init = true;
 
622
                }
 
623
 
 
624
                callbacks = new sasl_callback_t[5];
 
625
 
 
626
                callbacks[0].id = SASL_CB_GETREALM;
 
627
                callbacks[0].proc = 0;
 
628
                callbacks[0].context = 0;
 
629
 
 
630
                callbacks[1].id = SASL_CB_USER;
 
631
                callbacks[1].proc = 0;
 
632
                callbacks[1].context = 0;
 
633
 
 
634
                callbacks[2].id = SASL_CB_AUTHNAME;
 
635
                callbacks[2].proc = 0;
 
636
                callbacks[2].context = 0;
 
637
 
 
638
                callbacks[3].id = SASL_CB_PASS;
 
639
                callbacks[3].proc = 0;
 
640
                callbacks[3].context = 0;
 
641
 
 
642
                callbacks[4].id = SASL_CB_LIST_END;
 
643
                callbacks[4].proc = 0;
 
644
                callbacks[4].context = 0;
 
645
 
 
646
                result_result = Error;
 
647
 
 
648
                int r = sasl_client_new(service.toLatin1().data(), host.toLatin1().data(), localAddr.isEmpty() ? 0 : localAddr.toLatin1().data(), remoteAddr.isEmpty() ? 0 : remoteAddr.toLatin1().data(), callbacks, 0, &con);
 
649
                if(r != SASL_OK) {
 
650
                        setAuthCondition(r);
 
651
                        doResultsReady();
 
652
                        return;
 
653
                }
 
654
 
 
655
                if(!setsecprops())
 
656
                {
 
657
                        doResultsReady();
 
658
                        return;
 
659
                }
 
660
 
 
661
                result_mechlist = mechlist;
 
662
                servermode = false;
 
663
                step = 0;
 
664
                result_result = Success;
 
665
                clientTryAgain();
 
666
                doResultsReady();
 
667
                return;
 
668
        }
 
669
 
 
670
        // TODO: make use of disableServerSendLast
 
671
        virtual void startServer(const QString &realm, bool disableServerSendLast)
 
672
        {
 
673
                Q_UNUSED(disableServerSendLast);
 
674
                resetState();
 
675
 
 
676
                g->appname = SASL_APP;
 
677
                if(!g->server_init) {
 
678
                        sasl_server_init(NULL, QFile::encodeName(g->appname));
 
679
                        g->server_init = true;
 
680
                }
 
681
 
 
682
                callbacks = new sasl_callback_t[2];
 
683
 
 
684
                callbacks[0].id = SASL_CB_PROXY_POLICY;
 
685
                callbacks[0].proc = (int(*)())scb_checkauth;
 
686
                callbacks[0].context = this;
 
687
 
 
688
                callbacks[1].id = SASL_CB_LIST_END;
 
689
                callbacks[1].proc = 0;
 
690
                callbacks[1].context = 0;
 
691
 
 
692
                result_result = Error;
 
693
 
 
694
                int r = sasl_server_new(service.toLatin1().data(), host.toLatin1().data(), !realm.isEmpty() ? realm.toLatin1().data() : 0, localAddr.isEmpty() ? 0 : localAddr.toLatin1().data(), remoteAddr.isEmpty() ? 0 : remoteAddr.toLatin1().data(), callbacks, 0, &con);
 
695
                if(r != SASL_OK) {
 
696
                        setAuthCondition(r);
 
697
                        doResultsReady();
 
698
                        return;
 
699
                }
 
700
 
 
701
                if(!setsecprops())
 
702
                {
 
703
                        doResultsReady();
 
704
                        return;
 
705
                }
 
706
 
 
707
                const char *ml;
 
708
                r = sasl_listmech(con, 0, 0, " ", 0, &ml, 0, 0);
 
709
                if(r != SASL_OK)
 
710
                        return;
 
711
                result_mechlist = QString::fromUtf8(ml).split(' ');
 
712
 
 
713
                servermode = true;
 
714
                step = 0;
 
715
                ca_done = false;
 
716
                ca_skip = false;
 
717
                result_result = Success;
 
718
                doResultsReady();
 
719
                return;
 
720
        }
 
721
 
 
722
        virtual void serverFirstStep(const QString &mech, const QByteArray *clientInit)
 
723
        {
 
724
                in_mech = mech;
 
725
                if(clientInit) {
 
726
                        in_useClientInit = true;
 
727
                        in_clientInit = *clientInit;
 
728
                }
 
729
                else
 
730
                        in_useClientInit = false;
 
731
                serverTryAgain();
 
732
                doResultsReady();
 
733
        }
 
734
 
 
735
        virtual SASL::Params clientParams() const
 
736
        {
 
737
                SASLParams::SParams sparams = params.missing();
 
738
                return SASL::Params(sparams.user, sparams.authzid, sparams.pass, sparams.realm);
 
739
        }
 
740
 
 
741
        virtual void setClientParams(const QString *user, const QString *authzid, const SecureArray *pass, const QString *realm)
 
742
        {
 
743
                if(user)
 
744
                        params.setUsername(*user);
 
745
                if(authzid)
 
746
                        params.setAuthzid(*authzid);
 
747
                if(pass)
 
748
                        params.setPassword(*pass);
 
749
                if(realm)
 
750
                        params.setRealm(*realm);
 
751
        }
 
752
 
 
753
        virtual QString username() const
 
754
        {
 
755
                return sc_username;
 
756
        }
 
757
 
 
758
        virtual QString authzid() const
 
759
        {
 
760
                return sc_authzid;
 
761
        }
 
762
 
 
763
        virtual void nextStep(const QByteArray &from_net)
 
764
        {
 
765
                in_buf = from_net;
 
766
                tryAgain();
 
767
        }
 
768
 
 
769
        virtual void tryAgain()
 
770
        {
 
771
                if(servermode)
 
772
                        serverTryAgain();
 
773
                else
 
774
                        clientTryAgain();
 
775
                doResultsReady();
 
776
        }
 
777
 
 
778
        virtual QString mech() const
 
779
        {
 
780
                if (servermode)
 
781
                        return in_mech;
 
782
                else
 
783
                        return out_mech;
 
784
        }
 
785
 
 
786
        virtual QStringList mechlist() const
 
787
        {
 
788
                return result_mechlist;
 
789
        }
 
790
 
 
791
        virtual QStringList realmlist() const
 
792
        {
 
793
                // TODO
 
794
                return QStringList();
 
795
        }
 
796
 
 
797
        virtual void setConstraints(SASL::AuthFlags f, int minSSF, int maxSSF)
 
798
        {
 
799
                int sf = 0;
 
800
                if( !(f & SASL::AllowPlain) )
 
801
                        sf |= SASL_SEC_NOPLAINTEXT;
 
802
                // if( !(f & SASL::AllowActiveVulnerable) ) // TODO
 
803
                //      sf |= SASL_SEC_NOACTIVE;
 
804
                // if( !(f & SASL::AllowDictVulnerable) ) // TODO
 
805
                //      sf |= SASL_SEC_NODICTIONARY;
 
806
                if( !(f & SASL::AllowAnonymous) )
 
807
                        sf |= SASL_SEC_NOANONYMOUS;
 
808
                if( f & SASL::RequireForwardSecrecy )
 
809
                        sf |= SASL_SEC_FORWARD_SECRECY;
 
810
                if( f & SASL::RequirePassCredentials )
 
811
                        sf |= SASL_SEC_PASS_CREDENTIALS;
 
812
                if( f & SASL::RequireMutualAuth )
 
813
                        sf |= SASL_SEC_MUTUAL_AUTH;
 
814
 
 
815
                secflags = sf;
 
816
                ssf_min = minSSF;
 
817
                ssf_max = maxSSF;
 
818
        }
 
819
 
 
820
        virtual bool waitForResultsReady(int msecs)
 
821
        {
 
822
                // TODO: for now, all operations block anyway
 
823
                Q_UNUSED(msecs);
 
824
                return true;
 
825
        }
 
826
 
 
827
        virtual void update(const QByteArray &from_net, const QByteArray &from_app)
 
828
        {
 
829
                bool ok;
 
830
                if(!from_app.isEmpty())
 
831
                        ok = sasl_endecode(from_app, &result_to_net, true);
 
832
                else
 
833
                        ok = sasl_endecode(from_net, &result_plain, false);
 
834
                result_result = ok ? Success : Error;
 
835
 
 
836
                //printf("update (from_net=%d, to_net=%d, from_app=%d, to_app=%d)\n", from_net.size(), result_to_net.size(), from_app.size(), result_plain.size());
 
837
 
 
838
                doResultsReady();
 
839
        }
 
840
 
 
841
        virtual bool haveClientInit() const
 
842
        {
 
843
                return result_haveClientInit;
 
844
        }
 
845
 
 
846
        virtual QByteArray stepData() const
 
847
        {
 
848
                return out_buf;
 
849
        }
 
850
 
 
851
        virtual QByteArray to_net()
 
852
        {
 
853
                QByteArray a = result_to_net;
 
854
                result_to_net.clear();
 
855
                return a;
 
856
        }
 
857
 
 
858
        virtual int encoded() const
 
859
        {
 
860
                return result_ssf;
 
861
        }
 
862
 
 
863
        virtual QByteArray to_app()
 
864
        {
 
865
                QByteArray a = result_plain;
 
866
                result_plain.clear();
 
867
                return a;
 
868
        }
 
869
 
 
870
        virtual SASL::AuthCondition authCondition() const
 
871
        {
 
872
                return result_authCondition;
 
873
        }
 
874
};
 
875
 
 
876
//----------------------------------------------------------------------------
 
877
// saslProvider
 
878
//----------------------------------------------------------------------------
 
879
saslProvider::saslProvider()
 
880
{
 
881
        client_init = false;
 
882
        server_init = false;
 
883
}
 
884
 
 
885
void saslProvider::init()
 
886
{
 
887
}
 
888
 
 
889
saslProvider::~saslProvider()
 
890
{
 
891
        if(client_init || server_init)
 
892
                sasl_done();
 
893
}
 
894
 
 
895
int saslProvider::qcaVersion() const
 
896
{
 
897
        return QCA_VERSION;
 
898
}
 
899
 
 
900
QString saslProvider::name() const
 
901
{
 
902
        return "qca-cyrus-sasl";
 
903
}
 
904
 
 
905
QString saslProvider::credit() const
 
906
{
 
907
        return QString(); // TODO
 
908
}
 
909
 
 
910
QStringList saslProvider::features() const
 
911
{
 
912
        QStringList list;
 
913
        list += "sasl";
 
914
 
 
915
        return list;
 
916
}
 
917
 
 
918
Provider::Context *saslProvider::createContext(const QString &type)
 
919
{
 
920
        if ( type == "sasl" )
 
921
                return new saslContext( this );
 
922
 
 
923
        return 0;
 
924
}
 
925
 
 
926
} // namespace saslQCAPlugin
 
927
 
 
928
using namespace saslQCAPlugin;
 
929
 
 
930
//----------------------------------------------------------------------------
 
931
// saslPlugin
 
932
//----------------------------------------------------------------------------
 
933
 
 
934
class saslPlugin : public QObject, public QCAPlugin
 
935
{
 
936
        Q_OBJECT
 
937
        Q_INTERFACES(QCAPlugin)
 
938
public:
 
939
        virtual Provider *createProvider() { return new saslProvider; }
 
940
};
 
941
 
 
942
#include "qca-cyrus-sasl.moc"
 
943
 
 
944
Q_EXPORT_PLUGIN2(qca_cyrus_sasl, saslPlugin)
 
945