~ubuntu-branches/ubuntu/wily/qca2/wily-proposed

« back to all changes in this revision

Viewing changes to src/qca_securelayer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2007-10-27 18:51:54 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20071027185154-4ir9ys3h2q9fofrw
Tags: 2.0.0-2
Upload to unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
30
30
Provider::Context *getContext(const QString &type, const QString &provider);
31
31
 
 
32
enum ResetMode
 
33
{
 
34
        ResetSession        = 0,
 
35
        ResetSessionAndData = 1,
 
36
        ResetAll            = 2
 
37
};
 
38
 
32
39
//----------------------------------------------------------------------------
33
40
// LayerTracker
34
41
//----------------------------------------------------------------------------
147
154
//----------------------------------------------------------------------------
148
155
// TLS
149
156
//----------------------------------------------------------------------------
150
 
enum ResetMode
151
 
{
152
 
        ResetSession        = 0,
153
 
        ResetSessionAndData = 1,
154
 
        ResetAll            = 2
155
 
};
156
 
 
157
157
class TLS::Private : public QObject
158
158
{
159
159
        Q_OBJECT
160
160
public:
 
161
        enum
 
162
        {
 
163
                OpStart,
 
164
                OpUpdate
 
165
        };
 
166
 
 
167
        enum State
 
168
        {
 
169
                Inactive,
 
170
                Initializing,
 
171
                Handshaking,
 
172
                Connected,
 
173
                Closing
 
174
        };
 
175
 
 
176
        class Action
 
177
        {
 
178
        public:
 
179
                enum Type
 
180
                {
 
181
                        ReadyRead,
 
182
                        ReadyReadOutgoing,
 
183
                        Handshaken,
 
184
                        Close,
 
185
                        CheckPeerCertificate,
 
186
                        CertificateRequested,
 
187
                        HostNameReceived
 
188
                };
 
189
 
 
190
                int type;
 
191
 
 
192
                Action(int _type) : type(_type)
 
193
                {
 
194
                }
 
195
        };
 
196
 
161
197
        TLS *q;
162
198
        TLSContext *c;
163
199
        TLS::Mode mode;
164
200
 
165
 
        bool active, server;
 
201
        // signal connected flags
 
202
        bool connect_hostNameReceived;
 
203
        bool connect_certificateRequested;
 
204
        bool connect_peerCertificateAvailable;
 
205
        bool connect_handshaken;
 
206
 
 
207
        // persistent settings (survives ResetSessionAndData)
166
208
        CertificateChain localCert;
167
209
        PrivateKey localKey;
168
210
        CertificateCollection trusted;
169
211
        bool con_ssfMode;
170
212
        int con_minSSF, con_maxSSF;
171
213
        QStringList con_cipherSuites;
 
214
        bool tryCompress;
 
215
        int packet_mtu;
172
216
        QList<CertificateInfoOrdered> issuerList;
173
217
        TLSSession session;
174
 
        bool tryCompress;
175
 
        int packet_mtu;
176
218
 
 
219
        // session
 
220
        State state;
 
221
        bool blocked;
 
222
        bool server;
177
223
        QString host;
 
224
        TLSContext::SessionInfo sessionInfo;
 
225
        QTimer actionTrigger;
 
226
        int op;
 
227
        QList<Action> actionQueue;
 
228
        bool need_update;
 
229
        bool maybe_input;
 
230
        bool emitted_hostNameReceived;
 
231
        bool emitted_certificateRequested;
 
232
        bool emitted_peerCertificateAvailable;
 
233
 
 
234
        // data (survives ResetSession)
178
235
        CertificateChain peerCert;
179
236
        Validity peerValidity;
180
 
        bool blocked;
181
237
        bool hostMismatch;
182
 
        TLSContext::SessionInfo sessionInfo;
 
238
        Error errorCode;
183
239
 
 
240
        // stream i/o
184
241
        QByteArray in, out;
185
242
        QByteArray to_net, from_net;
186
 
        int pending_write;
 
243
        QByteArray unprocessed;
 
244
        int out_pending;
 
245
        int to_net_encoded;
187
246
        LayerTracker layer;
188
247
 
 
248
        // datagram i/o
189
249
        QList<QByteArray> packet_in, packet_out;
190
250
        QList<QByteArray> packet_to_net, packet_from_net;
 
251
        int packet_out_pending; // packet count
191
252
        QList<int> packet_to_net_encoded;
192
253
 
193
 
        bool connect_hostNameReceived, connect_certificateRequested, connect_handshaken;
194
 
 
195
 
        enum { OpStart, OpUpdate };
196
 
 
197
 
        int op;
198
 
 
199
 
        bool handshaken, closing;
200
 
        bool tryMore;
201
 
        int bytesEncoded;
202
 
        Error errorCode;
203
 
 
204
 
        Private(TLS *_q, TLS::Mode _mode) : QObject(_q), q(_q), mode(_mode)
 
254
        Private(TLS *_q, TLS::Mode _mode) : QObject(_q), q(_q), mode(_mode), actionTrigger(this)
205
255
        {
206
256
                // c is 0 during initial reset, so we don't redundantly reset it
207
257
                c = 0;
208
258
                connect_hostNameReceived = false;
209
259
                connect_certificateRequested = false;
 
260
                connect_peerCertificateAvailable = false;
210
261
                connect_handshaken = false;
211
262
                server = false;
212
263
 
 
264
                connect(&actionTrigger, SIGNAL(timeout()), SLOT(doNextAction()));
 
265
                actionTrigger.setSingleShot(true);
 
266
 
213
267
                reset(ResetAll);
214
268
 
215
269
                c = static_cast<TLSContext *>(q->context());
218
272
                c->setParent(this);
219
273
 
220
274
                connect(c, SIGNAL(resultsReady()), SLOT(tls_resultsReady()));
 
275
                connect(c, SIGNAL(dtlsTimeout()), SLOT(tls_dtlsTimeout()));
221
276
        }
222
277
 
223
278
        ~Private()
231
286
                if(c)
232
287
                        c->reset();
233
288
 
 
289
                // if we reset while in client mode, then clear this list
 
290
                //   (it should only persist when used for server mode)
234
291
                if(!server)
235
292
                        issuerList.clear();
236
 
                active = false;
 
293
 
 
294
                state = Inactive;
 
295
                blocked = false;
237
296
                server = false;
238
297
                host = QString();
 
298
                sessionInfo = TLSContext::SessionInfo();
 
299
                actionTrigger.stop();
 
300
                op = -1;
 
301
                actionQueue.clear();
 
302
                need_update = false;
 
303
                maybe_input = false;
 
304
                emitted_hostNameReceived = false;
 
305
                emitted_certificateRequested = false;
 
306
                emitted_peerCertificateAvailable = false;
 
307
 
239
308
                out.clear();
 
309
                out_pending = 0;
240
310
                packet_out.clear();
241
 
                handshaken = false;
242
 
                closing = false;
243
 
                tryMore = false;
244
 
                bytesEncoded = 0;
245
 
                op = -1;
246
 
                pending_write = 0;
247
 
                blocked = false;
248
 
                layer.reset();
 
311
                packet_out_pending = 0;
249
312
 
250
313
                if(mode >= ResetSessionAndData)
251
314
                {
252
315
                        peerCert = CertificateChain();
253
316
                        peerValidity = ErrorValidityUnknown;
254
317
                        hostMismatch = false;
 
318
                        errorCode = (TLS::Error)-1;
 
319
 
255
320
                        in.clear();
256
321
                        to_net.clear();
257
322
                        from_net.clear();
 
323
                        unprocessed.clear();
 
324
                        to_net_encoded = 0;
 
325
                        layer.reset();
 
326
 
258
327
                        packet_in.clear();
259
328
                        packet_to_net.clear();
 
329
                        packet_from_net.clear();
260
330
                        packet_to_net_encoded.clear();
261
 
                        packet_from_net.clear();
262
331
                }
263
332
 
264
333
                if(mode >= ResetAll)
279
348
 
280
349
        void start(bool serverMode)
281
350
        {
282
 
                active = true;
 
351
                state = Initializing;
283
352
                server = serverMode;
284
353
 
285
354
                c->setup(serverMode, host, tryCompress);
300
369
                }
301
370
                c->setMTU(packet_mtu);
302
371
 
 
372
                QCA_logTextMessage(QString("tls[%1]: c->start()").arg(q->objectName()), Logger::Information);
303
373
                op = OpStart;
304
374
                c->start();
305
375
        }
306
376
 
307
377
        void close()
308
378
        {
309
 
                if(!handshaken || closing)
 
379
                QCA_logTextMessage(QString("tls[%1]: close").arg(q->objectName()), Logger::Information);
 
380
 
 
381
                if(state != Connected)
310
382
                        return;
311
383
 
312
 
                closing = true;
 
384
                state = Closing;
313
385
                c->shutdown();
314
386
        }
315
387
 
316
388
        void continueAfterStep()
317
389
        {
318
 
                //printf("continuing\n");
 
390
                QCA_logTextMessage(QString("tls[%1]: continueAfterStep").arg(q->objectName()), Logger::Information);
 
391
 
 
392
                if(!blocked)
 
393
                        return;
319
394
 
320
395
                blocked = false;
321
396
                update();
322
397
        }
323
398
 
 
399
        void processNextAction()
 
400
        {
 
401
                if(actionQueue.isEmpty())
 
402
                {
 
403
                        if(need_update)
 
404
                        {
 
405
                                QCA_logTextMessage(QString("tls[%1]: need_update").arg(q->objectName()), Logger::Information);
 
406
                                update();
 
407
                        }
 
408
                        return;
 
409
                }
 
410
 
 
411
                Action a = actionQueue.takeFirst();
 
412
 
 
413
                // set up for the next one, if necessary
 
414
                if(!actionQueue.isEmpty() || need_update)
 
415
                {
 
416
                        if(!actionTrigger.isActive())
 
417
                                actionTrigger.start();
 
418
                }
 
419
 
 
420
                if(a.type == Action::ReadyRead)
 
421
                {
 
422
                        emit q->readyRead();
 
423
                }
 
424
                else if(a.type == Action::ReadyReadOutgoing)
 
425
                {
 
426
                        emit q->readyReadOutgoing();
 
427
                }
 
428
                else if(a.type == Action::Handshaken)
 
429
                {
 
430
                        state = Connected;
 
431
 
 
432
                        // write any app data waiting during handshake
 
433
                        if(!out.isEmpty())
 
434
                        {
 
435
                                need_update = true;
 
436
                                if(!actionTrigger.isActive())
 
437
                                        actionTrigger.start();
 
438
                        }
 
439
 
 
440
                        QCA_logTextMessage(QString("tls[%1]: handshaken").arg(q->objectName()), Logger::Information);
 
441
 
 
442
                        if(connect_handshaken)
 
443
                        {
 
444
                                blocked = true;
 
445
                                emit q->handshaken();
 
446
                        }
 
447
                }
 
448
                else if(a.type == Action::Close)
 
449
                {
 
450
                        unprocessed = c->unprocessed();
 
451
                        reset(ResetSession);
 
452
                        emit q->closed();
 
453
                }
 
454
                else if(a.type == Action::CheckPeerCertificate)
 
455
                {
 
456
                        peerCert = c->peerCertificateChain();
 
457
                        if(!peerCert.isEmpty())
 
458
                        {
 
459
                                peerValidity = c->peerCertificateValidity();
 
460
                                if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostName(host))
 
461
                                        hostMismatch = true;
 
462
                        }
 
463
 
 
464
                        if(connect_peerCertificateAvailable)
 
465
                        {
 
466
                                blocked = true;
 
467
                                emitted_peerCertificateAvailable = true;
 
468
                                emit q->peerCertificateAvailable();
 
469
                        }
 
470
                }
 
471
                else if(a.type == Action::CertificateRequested)
 
472
                {
 
473
                        issuerList = c->issuerList();
 
474
                        if(connect_certificateRequested)
 
475
                        {
 
476
                                blocked = true;
 
477
                                emitted_certificateRequested = true;
 
478
                                emit q->certificateRequested();
 
479
                        }
 
480
                }
 
481
                else if(a.type == Action::HostNameReceived)
 
482
                {
 
483
                        if(connect_hostNameReceived)
 
484
                        {
 
485
                                blocked = true;
 
486
                                emitted_hostNameReceived = true;
 
487
                                emit q->hostNameReceived();
 
488
                        }
 
489
                }
 
490
        }
 
491
 
324
492
        void update()
325
493
        {
326
 
                //printf("update attempt\n");
 
494
                QCA_logTextMessage(QString("tls[%1]: update").arg(q->objectName()), Logger::Information);
 
495
 
327
496
                if(blocked)
328
 
                        return;
 
497
                {
 
498
                        QCA_logTextMessage(QString("tls[%1]: ignoring update while blocked").arg(q->objectName()), Logger::Information);
 
499
                        return;
 
500
                }
 
501
 
 
502
                if(!actionQueue.isEmpty())
 
503
                {
 
504
                        QCA_logTextMessage(QString("tls[%1]: ignoring update while processing actions").arg(q->objectName()), Logger::Information);
 
505
                        need_update = true;
 
506
                        return;
 
507
                }
329
508
 
330
509
                // only allow one operation at a time
331
510
                if(op != -1)
 
511
                {
 
512
                        QCA_logTextMessage(QString("tls[%1]: ignoring update while operation active").arg(q->objectName()), Logger::Information);
332
513
                        return;
333
 
 
334
 
                //printf("update\n");
335
 
 
336
 
                if(!handshaken)
 
514
                }
 
515
 
 
516
                need_update = false;
 
517
 
 
518
                QByteArray arg_from_net, arg_from_app;
 
519
 
 
520
                if(state == Handshaking)
337
521
                {
338
 
                        // FIXME: optimize this somehow.  we need to force
339
 
                        //   the update after start() succeeds, but not in any
340
 
                        //   other case afaict.
 
522
                        // during handshake, only send from_net (no app data)
341
523
 
342
524
                        if(mode == TLS::Stream)
343
525
                        {
344
 
                                // during handshake, only send from_net (no app data)
345
 
                                //if(!from_net.isEmpty())
346
 
                                //{
347
 
                                        op = OpUpdate;
348
 
                                        c->update(from_net, QByteArray());
349
 
                                        from_net.clear();
350
 
                                //}
 
526
                                arg_from_net = from_net;
 
527
                                from_net.clear();
351
528
                        }
352
529
                        else
353
530
                        {
354
531
                                // note: there may not be a packet
355
 
                                QByteArray pkt = packet_from_net.takeFirst();
356
 
 
357
 
                                op = OpUpdate;
358
 
                                c->update(pkt, QByteArray());
 
532
                                if(!packet_from_net.isEmpty())
 
533
                                        arg_from_net = packet_from_net.takeFirst();
359
534
                        }
360
535
                }
361
536
                else
362
537
                {
363
538
                        if(mode == TLS::Stream)
364
539
                        {
365
 
                                // FIXME: we should be able to send both at once,
366
 
                                //   but if we do this then qca-ossl gives us
367
 
                                //   broken security layer.  probably a bug in
368
 
                                //   qca-ossl?
369
 
 
370
 
                                // otherwise, send both from_net and out
371
 
                                /*if(!from_net.isEmpty() || !out.isEmpty())
372
 
                                {
373
 
                                        op = OpUpdate;
374
 
                                        pending_write += out.size();
375
 
                                        c->update(from_net, out);
376
 
                                        from_net.clear();
377
 
                                        out.clear();
378
 
                                }*/
379
 
 
380
540
                                if(!from_net.isEmpty())
381
541
                                {
382
 
                                        op = OpUpdate;
383
 
                                        c->update(from_net, QByteArray());
 
542
                                        arg_from_net = from_net;
384
543
                                        from_net.clear();
385
544
                                }
386
 
                                else //if(!out.isEmpty())
 
545
 
 
546
                                if(!out.isEmpty())
387
547
                                {
388
 
                                        op = OpUpdate;
389
 
                                        pending_write += out.size();
390
 
                                        c->update(QByteArray(), out);
 
548
                                        out_pending += out.size();
 
549
                                        arg_from_app = out;
391
550
                                        out.clear();
392
551
                                }
393
552
                        }
394
553
                        else
395
554
                        {
396
 
                                op = OpUpdate;
397
 
                                QByteArray pkta = packet_from_net.takeFirst();
398
 
                                QByteArray pktb = packet_out.takeFirst();
399
 
                                if(!pktb.isEmpty())
400
 
                                        packet_to_net_encoded += pktb.size();
401
 
                                c->update(pkta, pktb);
 
555
                                if(!packet_from_net.isEmpty())
 
556
                                        arg_from_net = packet_from_net.takeFirst();
 
557
 
 
558
                                if(!packet_out.isEmpty())
 
559
                                {
 
560
                                        arg_from_app = packet_out.takeFirst();
 
561
                                        ++packet_out_pending;
 
562
                                }
402
563
                        }
403
564
                }
404
 
        }
405
 
 
406
 
private slots:
407
 
        void tls_resultsReady()
408
 
        {
409
 
                QPointer<QObject> self = this;
410
 
 
411
 
                int last_op = op;
412
 
                op = -1;
413
 
                //printf("results ready: %d\n", last_op);
414
 
 
415
 
                if(last_op == OpStart)
416
 
                {
417
 
                        bool ok = c->result() == TLSContext::Success;
418
 
                        if(!ok)
 
565
 
 
566
                if(arg_from_net.isEmpty() && arg_from_app.isEmpty() && !maybe_input)
 
567
                {
 
568
                        QCA_logTextMessage(QString("tls[%1]: ignoring update: no output and no expected input").arg(q->objectName()), Logger::Information);
 
569
                        return;
 
570
                }
 
571
 
 
572
                // clear this flag
 
573
                maybe_input = false;
 
574
 
 
575
                QCA_logTextMessage(QString("tls[%1]: c->update").arg(q->objectName()), Logger::Information);
 
576
                op = OpUpdate;
 
577
                c->update(arg_from_net, arg_from_app);
 
578
        }
 
579
 
 
580
        void start_finished()
 
581
        {
 
582
                bool ok = c->result() == TLSContext::Success;
 
583
                if(!ok)
 
584
                {
 
585
                        reset(ResetSession);
 
586
                        errorCode = TLS::ErrorInit;
 
587
                        emit q->error();
 
588
                        return;
 
589
                }
 
590
 
 
591
                state = Handshaking;
 
592
 
 
593
                // immediately update so we can get the first packet to send
 
594
                maybe_input = true;
 
595
                update();
 
596
        }
 
597
 
 
598
        void update_finished()
 
599
        {
 
600
                TLSContext::Result r = c->result();
 
601
                if(r == TLSContext::Error)
 
602
                {
 
603
                        if(state == Handshaking || state == Closing)
419
604
                        {
420
605
                                reset(ResetSession);
421
 
                                errorCode = TLS::ErrorInit;
422
 
                                QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
423
 
                                //emit q->error();
424
 
                                return;
425
 
                        }
426
 
 
427
 
                        update();
428
 
                }
429
 
                else // OpUpdate
430
 
                {
431
 
                        TLSContext::Result r = c->result();
432
 
                        QByteArray a = c->to_net();
433
 
 
434
 
                        if(closing)
435
 
                        {
436
 
                                if(r == TLSContext::Error)
437
 
                                {
438
 
                                        reset(ResetSession);
439
 
                                        errorCode = ErrorHandshake;
440
 
                                        QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
441
 
                                        //emit q->error();
442
 
                                        return;
443
 
                                }
444
 
 
445
 
                                if(mode == TLS::Stream)
446
 
                                        to_net.append(a);
447
 
                                else
448
 
                                        packet_to_net += a;
449
 
 
450
 
                                if(!a.isEmpty())
451
 
                                {
452
 
                                        QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
453
 
                                        //emit q->readyReadOutgoing();
454
 
                                        if(!self)
455
 
                                                return;
456
 
                                }
457
 
 
458
 
                                if(r == TLSContext::Success)
459
 
                                {
460
 
                                        from_net = c->unprocessed();
461
 
                                        reset(ResetSession);
462
 
                                        QMetaObject::invokeMethod(q, "closed", Qt::QueuedConnection);
463
 
                                        //emit q->closed();
464
 
                                        return;
465
 
                                }
466
 
 
467
 
                                return;
468
 
                        }
469
 
 
470
 
                        if(!handshaken)
471
 
                        {
472
 
                                if(r == TLSContext::Error)
473
 
                                {
474
 
                                        reset(ResetSession);
475
 
                                        errorCode = TLS::ErrorHandshake;
476
 
                                        QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
477
 
                                        //emit q->error();
478
 
                                        return;
479
 
                                }
480
 
 
481
 
                                if(mode == TLS::Stream)
482
 
                                        to_net.append(a);
483
 
                                else
484
 
                                        packet_to_net += a;
485
 
 
486
 
                                if(!a.isEmpty())
487
 
                                {
488
 
                                        QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
489
 
                                        //emit q->readyReadOutgoing();
490
 
                                        if(!self)
491
 
                                                return;
492
 
                                }
493
 
 
494
 
                                if(r == TLSContext::Success)
495
 
                                {
496
 
                                        peerCert = c->peerCertificateChain();
497
 
                                        if(!peerCert.isEmpty())
498
 
                                        {
499
 
                                                peerValidity = c->peerCertificateValidity();
500
 
                                                if(peerValidity == ValidityGood && !host.isEmpty() && !peerCert.primary().matchesHostName(host))
501
 
                                                        hostMismatch = true;
502
 
                                        }
503
 
 
504
 
                                        sessionInfo = c->sessionInfo();
505
 
                                        if(sessionInfo.id)
506
 
                                        {
507
 
                                                TLSSessionContext *sc = static_cast<TLSSessionContext*>(sessionInfo.id->clone());
508
 
                                                session.change(sc);
509
 
                                        }
510
 
 
511
 
                                        handshaken = true;
512
 
                                        if(connect_handshaken)
513
 
                                        {
514
 
                                                blocked = true;
515
 
                                                emit q->handshaken();
516
 
                                        }
517
 
                                        // FIXME: else?
518
 
                                        return;
519
 
                                }
520
 
                                else // Continue
521
 
                                {
522
 
                                        if(server)
523
 
                                        {
524
 
                                                bool clientHello = c->clientHelloReceived();
525
 
                                                if(clientHello)
526
 
                                                {
527
 
                                                        host = c->hostName();
528
 
                                                        if(!host.isEmpty())
529
 
                                                        {
530
 
                                                                if(connect_hostNameReceived)
531
 
                                                                {
532
 
                                                                        blocked = true;
533
 
                                                                        emit q->hostNameReceived();
534
 
                                                                        if(!self)
535
 
                                                                                return;
536
 
                                                                }
537
 
                                                        }
538
 
                                                }
539
 
                                                return;
540
 
                                        }
541
 
                                        else
542
 
                                        {
543
 
                                                bool serverHello = c->serverHelloReceived();
544
 
                                                if(serverHello)
545
 
                                                {
546
 
                                                        if(c->certificateRequested())
547
 
                                                        {
548
 
                                                                issuerList = c->issuerList();
549
 
                                                                if(connect_certificateRequested)
550
 
                                                                {
551
 
                                                                        blocked = true;
552
 
                                                                        emit q->certificateRequested();
553
 
                                                                        if(!self)
554
 
                                                                                return;
555
 
                                                                }
556
 
                                                        }
557
 
                                                }
558
 
                                                return;
559
 
                                        }
560
 
                                }
561
 
 
562
 
                                return;
563
 
                        }
564
 
 
565
 
                        bool ok = (r == TLSContext::Success);
566
 
                        if(!ok)
 
606
                                errorCode = ErrorHandshake;
 
607
                        }
 
608
                        else
567
609
                        {
568
610
                                reset(ResetSession);
569
611
                                errorCode = ErrorCrypt;
570
 
                                QMetaObject::invokeMethod(q, "error", Qt::QueuedConnection);
571
 
                                //emit q->error();
572
 
                                return;
573
 
                        }
574
 
 
575
 
                        QByteArray b = c->to_app();
576
 
                        //printf("to_app: %d (%s)\n", b.size(), b.data());
 
612
                        }
 
613
 
 
614
                        emit q->error();
 
615
                        return;
 
616
                }
 
617
 
 
618
                QByteArray c_to_net = c->to_net();
 
619
                if(!c_to_net.isEmpty())
 
620
                {
 
621
                        QCA_logTextMessage(QString("tls[%1]: to_net %2").arg(q->objectName(), QString::number(c_to_net.size())), Logger::Information);
 
622
                }
 
623
 
 
624
                if(state == Closing)
 
625
                {
 
626
                        if(mode == TLS::Stream)
 
627
                                to_net += c_to_net;
 
628
                        else
 
629
                                packet_to_net += c_to_net;
 
630
 
 
631
                        if(!c_to_net.isEmpty())
 
632
                                actionQueue += Action(Action::ReadyReadOutgoing);
 
633
 
 
634
                        if(r == TLSContext::Success)
 
635
                                actionQueue += Action(Action::Close);
 
636
 
 
637
                        processNextAction();
 
638
                        return;
 
639
                }
 
640
                else if(state == Handshaking)
 
641
                {
 
642
                        if(mode == TLS::Stream)
 
643
                                to_net += c_to_net;
 
644
                        else
 
645
                                packet_to_net += c_to_net;
 
646
 
 
647
                        if(!c_to_net.isEmpty())
 
648
                                actionQueue += Action(Action::ReadyReadOutgoing);
 
649
 
 
650
                        bool clientHello = false;
 
651
                        bool serverHello = false;
 
652
                        if(server)
 
653
                                clientHello = c->clientHelloReceived();
 
654
                        else
 
655
                                serverHello = c->serverHelloReceived();
 
656
 
 
657
                        // client specifies a host?
 
658
                        if(!emitted_hostNameReceived && clientHello)
 
659
                        {
 
660
                                host = c->hostName();
 
661
                                if(!host.isEmpty())
 
662
                                        actionQueue += Action(Action::HostNameReceived);
 
663
                        }
 
664
 
 
665
                        // successful handshake or server hello means there might be a peer cert
 
666
                        if(!emitted_peerCertificateAvailable && (r == TLSContext::Success || (!server && serverHello)))
 
667
                                actionQueue += Action(Action::CheckPeerCertificate);
 
668
 
 
669
                        // server requests a cert from us?
 
670
                        if(!emitted_certificateRequested && (serverHello && c->certificateRequested()))
 
671
                                actionQueue += Action(Action::CertificateRequested);
 
672
 
 
673
                        if(r == TLSContext::Success)
 
674
                        {
 
675
                                sessionInfo = c->sessionInfo();
 
676
                                if(sessionInfo.id)
 
677
                                {
 
678
                                        TLSSessionContext *sc = static_cast<TLSSessionContext*>(sessionInfo.id->clone());
 
679
                                        session.change(sc);
 
680
                                }
 
681
 
 
682
                                actionQueue += Action(Action::Handshaken);
 
683
                        }
 
684
 
 
685
                        processNextAction();
 
686
                        return;
 
687
                }
 
688
                else // Connected
 
689
                {
 
690
                        QByteArray c_to_app = c->to_app();
 
691
                        if(!c_to_app.isEmpty())
 
692
                        {
 
693
                                QCA_logTextMessage(QString("tls[%1]: to_app %2").arg(q->objectName(), QString::number(c_to_app.size())), Logger::Information);
 
694
                        }
 
695
 
577
696
                        bool eof = c->eof();
578
 
                        int enc = c->encoded();
 
697
                        int enc = -1;
 
698
                        if(!c_to_net.isEmpty())
 
699
                                enc = c->encoded();
579
700
 
580
 
                        bool more = false;
 
701
                        bool io_pending = false;
581
702
                        if(mode == TLS::Stream)
582
703
                        {
583
 
                                pending_write -= enc;
584
 
                                if(pending_write > 0)
585
 
                                        more = true;
 
704
                                if(!c_to_net.isEmpty())
 
705
                                        out_pending -= enc;
 
706
 
 
707
                                if(out_pending > 0)
 
708
                                {
 
709
                                        maybe_input = true;
 
710
                                        io_pending = true;
 
711
                                }
 
712
 
 
713
                                if(!out.isEmpty())
 
714
                                        io_pending = true;
586
715
                        }
587
716
                        else
588
717
                        {
589
 
                                if(!a.isEmpty() && enc > 0)
 
718
                                if(!c_to_net.isEmpty())
 
719
                                        --packet_out_pending;
 
720
 
 
721
                                if(packet_out_pending > 0)
590
722
                                {
591
 
                                        enc = packet_to_net_encoded.takeFirst();
592
 
                                        if(!packet_to_net_encoded.isEmpty())
593
 
                                                more = true;
 
723
                                        maybe_input = true;
 
724
                                        io_pending = true;
594
725
                                }
595
726
 
596
 
                                // datagram mode might have more pending out
597
727
                                if(!packet_out.isEmpty())
598
 
                                        more = true;
 
728
                                        io_pending = true;
599
729
                        }
600
730
 
601
 
                        if(!out.isEmpty())
602
 
                                more = true;
603
 
 
604
731
                        if(mode == TLS::Stream)
605
732
                        {
606
 
                                to_net.append(a);
607
 
                                in.append(b);
608
 
                                bytesEncoded += enc;
 
733
                                to_net += c_to_net;
 
734
                                in += c_to_app;
 
735
                                to_net_encoded += enc;
609
736
                        }
610
737
                        else
611
738
                        {
612
 
                                packet_to_net += a;
613
 
                                packet_in += b;
614
 
                        }
615
 
 
616
 
                        if(!a.isEmpty())
617
 
                        {
618
 
                                QMetaObject::invokeMethod(q, "readyReadOutgoing", Qt::QueuedConnection);
619
 
                                //emit q->readyReadOutgoing();
620
 
                                if(!self)
621
 
                                        return;
622
 
                        }
623
 
 
624
 
                        if(!b.isEmpty())
625
 
                        {
626
 
                                QMetaObject::invokeMethod(q, "readyRead", Qt::QueuedConnection);
627
 
                                //emit q->readyRead();
628
 
                                if(!self)
629
 
                                        return;
630
 
                        }
 
739
                                packet_to_net += c_to_net;
 
740
                                packet_in += c_to_app;
 
741
                        }
 
742
 
 
743
                        if(!c_to_net.isEmpty())
 
744
                                actionQueue += Action(Action::ReadyReadOutgoing);
 
745
 
 
746
                        if(!c_to_app.isEmpty())
 
747
                                actionQueue += Action(Action::ReadyRead);
631
748
 
632
749
                        if(eof)
 
750
                        {
633
751
                                close();
 
752
                                maybe_input = true;
 
753
                        }
634
754
 
635
 
                        if(eof || more)
 
755
                        if(eof || io_pending)
 
756
                        {
 
757
                                QCA_logTextMessage(QString("tls[%1]: eof || io_pending").arg(q->objectName()), Logger::Information);
636
758
                                update();
 
759
                        }
 
760
 
 
761
                        processNextAction();
 
762
                        return;
637
763
                }
638
764
        }
 
765
 
 
766
private slots:
 
767
        void tls_resultsReady()
 
768
        {
 
769
                QCA_logTextMessage(QString("tls[%1]: c->resultsReady()").arg(q->objectName()), Logger::Information);
 
770
 
 
771
                Q_ASSERT(op != -1);
 
772
 
 
773
                int last_op = op;
 
774
                op = -1;
 
775
 
 
776
                if(last_op == OpStart)
 
777
                        start_finished();
 
778
                else // OpUpdate
 
779
                        update_finished();
 
780
        }
 
781
 
 
782
        void tls_dtlsTimeout()
 
783
        {
 
784
                QCA_logTextMessage(QString("tls[%1]: c->dtlsTimeout()").arg(q->objectName()), Logger::Information);
 
785
 
 
786
                maybe_input = true;
 
787
                update();
 
788
        }
 
789
 
 
790
        void doNextAction()
 
791
        {
 
792
                processNextAction();
 
793
        }
639
794
};
640
795
 
641
796
TLS::TLS(QObject *parent, const QString &provider)
669
824
{
670
825
        d->localCert = cert;
671
826
        d->localKey = key;
672
 
        if(d->active)
 
827
        if(d->state != TLS::Private::Inactive)
673
828
                d->c->setCertificate(cert, key);
674
829
}
675
830
 
686
841
void TLS::setTrustedCertificates(const CertificateCollection &trusted)
687
842
{
688
843
        d->trusted = trusted;
689
 
        if(d->active)
 
844
        if(d->state != TLS::Private::Inactive)
690
845
                d->c->setTrustedCertificates(trusted);
691
846
}
692
847
 
719
874
        d->con_minSSF = min;
720
875
        d->con_maxSSF = -1;
721
876
 
722
 
        if(d->active)
 
877
        if(d->state != TLS::Private::Inactive)
723
878
                d->c->setConstraints(d->con_minSSF, d->con_maxSSF);
724
879
}
725
880
 
729
884
        d->con_minSSF = minSSF;
730
885
        d->con_maxSSF = maxSSF;
731
886
 
732
 
        if(d->active)
 
887
        if(d->state != TLS::Private::Inactive)
733
888
                d->c->setConstraints(d->con_minSSF, d->con_maxSSF);
734
889
}
735
890
 
738
893
        d->con_ssfMode = false;
739
894
        d->con_cipherSuites = cipherSuiteList;
740
895
 
741
 
        if(d->active)
 
896
        if(d->state != TLS::Private::Inactive)
742
897
                d->c->setConstraints(d->con_cipherSuites);
743
898
}
744
899
 
750
905
void TLS::setIssuerList(const QList<CertificateInfoOrdered> &issuers)
751
906
{
752
907
        d->issuerList = issuers;
753
 
        if(d->active)
 
908
        if(d->state != TLS::Private::Inactive)
754
909
                d->c->setIssuerList(issuers);
755
910
}
756
911
 
804
959
 
805
960
bool TLS::isHandshaken() const
806
961
{
807
 
        return d->handshaken;
 
962
        if(d->state == TLS::Private::Connected || d->state == TLS::Private::Closing)
 
963
                return true;
 
964
        else
 
965
                return false;
808
966
}
809
967
 
810
968
bool TLS::isCompressed() const
912
1070
        }
913
1071
        else
914
1072
                d->packet_out.append(a);
 
1073
        QCA_logTextMessage(QString("tls[%1]: write").arg(objectName()), Logger::Information);
915
1074
        d->update();
916
1075
}
917
1076
 
924
1083
                return a;
925
1084
        }
926
1085
        else
927
 
                return d->packet_in.takeFirst();
 
1086
        {
 
1087
                if(!d->packet_in.isEmpty())
 
1088
                        return d->packet_in.takeFirst();
 
1089
                else
 
1090
                        return QByteArray();
 
1091
        }
928
1092
}
929
1093
 
930
1094
void TLS::writeIncoming(const QByteArray &a)
933
1097
                d->from_net.append(a);
934
1098
        else
935
1099
                d->packet_from_net.append(a);
 
1100
        QCA_logTextMessage(QString("tls[%1]: writeIncoming %2").arg(objectName(), QString::number(a.size())), Logger::Information);
936
1101
        d->update();
937
1102
}
938
1103
 
943
1108
                QByteArray a = d->to_net;
944
1109
                d->to_net.clear();
945
1110
                if(plainBytes)
946
 
                        *plainBytes = d->bytesEncoded;
947
 
                d->layer.specifyEncoded(a.size(), d->bytesEncoded);
948
 
                d->bytesEncoded = 0;
 
1111
                        *plainBytes = d->to_net_encoded;
 
1112
                d->layer.specifyEncoded(a.size(), d->to_net_encoded);
 
1113
                d->to_net_encoded = 0;
949
1114
                return a;
950
1115
        }
951
1116
        else
952
1117
        {
953
 
                QByteArray a = d->packet_to_net.takeFirst();
954
 
                int x = d->packet_to_net_encoded.takeFirst();
955
 
                if(plainBytes)
956
 
                        *plainBytes = x;
957
 
                return a;
 
1118
                if(!d->packet_to_net.isEmpty())
 
1119
                {
 
1120
                        QByteArray a = d->packet_to_net.takeFirst();
 
1121
                        int x = d->packet_to_net_encoded.takeFirst();
 
1122
                        if(plainBytes)
 
1123
                                *plainBytes = x;
 
1124
                        return a;
 
1125
                }
 
1126
                else
 
1127
                {
 
1128
                        if(plainBytes)
 
1129
                                *plainBytes = 0;
 
1130
                        return QByteArray();
 
1131
                }
958
1132
        }
959
1133
}
960
1134
 
962
1136
{
963
1137
        if(d->mode == Stream)
964
1138
        {
965
 
                QByteArray a = d->from_net;
966
 
                d->from_net.clear();
 
1139
                QByteArray a = d->unprocessed;
 
1140
                d->unprocessed.clear();
967
1141
                return a;
968
1142
        }
969
1143
        else
993
1167
void TLS::setPacketMTU(int size) const
994
1168
{
995
1169
        d->packet_mtu = size;
996
 
        if(d->active)
 
1170
        if(d->state != TLS::Private::Inactive)
997
1171
                d->c->setMTU(size);
998
1172
}
999
1173
 
1003
1177
                d->connect_hostNameReceived = true;
1004
1178
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(certificateRequested())))
1005
1179
                d->connect_certificateRequested = true;
 
1180
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(peerCertificateAvailable())))
 
1181
                d->connect_peerCertificateAvailable = true;
1006
1182
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(handshaken())))
1007
1183
                d->connect_handshaken = true;
1008
1184
}
1013
1189
                d->connect_hostNameReceived = false;
1014
1190
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(certificateRequested())))
1015
1191
                d->connect_certificateRequested = false;
 
1192
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(peerCertificateAvailable())))
 
1193
                d->connect_peerCertificateAvailable = false;
1016
1194
        else if(signal == QMetaObject::normalizedSignature(SIGNAL(handshaken())))
1017
1195
                d->connect_handshaken = false;
1018
1196
}
1097
1275
{
1098
1276
        Q_OBJECT
1099
1277
public:
1100
 
        SASL *q;
1101
 
        SASLContext *c;
1102
 
 
1103
1278
        enum
1104
1279
        {
1105
1280
                OpStart,
1109
1284
                OpUpdate
1110
1285
        };
1111
1286
 
 
1287
        class Action
 
1288
        {
 
1289
        public:
 
1290
                enum Type
 
1291
                {
 
1292
                        ClientStarted,
 
1293
                        NextStep,
 
1294
                        Authenticated,
 
1295
                        ReadyRead,
 
1296
                        ReadyReadOutgoing
 
1297
                };
 
1298
 
 
1299
                int type;
 
1300
                QByteArray stepData;
 
1301
                bool haveInit;
 
1302
 
 
1303
                Action(int _type) : type(_type)
 
1304
                {
 
1305
                }
 
1306
 
 
1307
                Action(int _type, const QByteArray &_stepData) : type(_type), stepData(_stepData)
 
1308
                {
 
1309
                }
 
1310
 
 
1311
                Action(int _type, bool _haveInit, const QByteArray &_stepData) : type(_type), stepData(_stepData), haveInit(_haveInit)
 
1312
                {
 
1313
                }
 
1314
        };
 
1315
 
 
1316
        SASL *q;
 
1317
        SASLContext *c;
 
1318
 
 
1319
        // persistent settings (survives ResetSessionAndData)
1112
1320
        AuthFlags auth_flags;
1113
1321
        int ssfmin, ssfmax;
1114
1322
        QString ext_authid;
1115
1323
        int ext_ssf;
1116
1324
        bool localSet, remoteSet;
1117
1325
        SASLContext::HostPort local, remote;
1118
 
 
1119
1326
        bool set_username, set_authzid, set_password, set_realm;
1120
1327
        QString username, authzid, realm;
1121
1328
        SecureArray password;
1122
1329
 
 
1330
        // session
1123
1331
        bool server;
1124
1332
        QStringList mechlist;
1125
1333
        QString server_realm;
1126
1334
        bool allowClientSendFirst;
1127
1335
        bool disableServerSendLast;
1128
 
 
 
1336
        QTimer actionTrigger;
1129
1337
        int op;
 
1338
        QList<Action> actionQueue;
 
1339
        bool need_update;
1130
1340
        bool first;
1131
1341
        bool authed;
 
1342
 
 
1343
        // data (survives ResetSession)
 
1344
        QString mech; // selected mech
1132
1345
        Error errorCode;
1133
 
        QByteArray out;
1134
 
        QByteArray in;
1135
 
        QByteArray to_net;
1136
 
        QByteArray from_net;
1137
 
        int bytesEncoded;
1138
 
        int pending_write;
 
1346
 
 
1347
        // stream i/o
 
1348
        QByteArray in, out;
 
1349
        QByteArray to_net, from_net;
 
1350
        int out_pending;
 
1351
        int to_net_encoded;
1139
1352
        LayerTracker layer;
1140
1353
 
1141
 
        Private(SASL *_q) : QObject(_q), q(_q)
 
1354
        Private(SASL *_q) : QObject(_q), q(_q), actionTrigger(this)
1142
1355
        {
1143
1356
                c = 0;
1144
1357
                set_username = false;
1146
1359
                set_password = false;
1147
1360
                set_realm = false;
1148
1361
 
 
1362
                connect(&actionTrigger, SIGNAL(timeout()), SLOT(doNextAction()));
 
1363
                actionTrigger.setSingleShot(true);
 
1364
 
1149
1365
                reset(ResetAll);
1150
1366
 
1151
1367
                c = static_cast<SASLContext *>(q->context());
1165
1381
        void reset(ResetMode mode)
1166
1382
        {
1167
1383
                if(c)
1168
 
                {
1169
1384
                        c->reset();
1170
1385
 
1171
 
                        if(mode < ResetAll)
1172
 
                        {
1173
 
                                QString *p_username = 0;
1174
 
                                QString *p_authzid = 0;
1175
 
                                SecureArray *p_password = 0;
1176
 
                                QString *p_realm = 0;
1177
 
 
1178
 
                                if(set_username)
1179
 
                                        p_username = &username;
1180
 
                                if(set_authzid)
1181
 
                                        p_authzid = &authzid;
1182
 
                                if(set_password)
1183
 
                                        p_password = &password;
1184
 
                                if(set_realm)
1185
 
                                        p_realm = &realm;
1186
 
 
1187
 
                                c->setClientParams(p_username, p_authzid, p_password, p_realm);
1188
 
                        }
1189
 
                }
1190
 
 
 
1386
                server = false;
 
1387
                mechlist.clear();
 
1388
                server_realm = QString();
 
1389
                allowClientSendFirst = false;
 
1390
                disableServerSendLast = true;
 
1391
                actionTrigger.stop();
1191
1392
                op = -1;
 
1393
                actionQueue.clear();
 
1394
                need_update = false;
 
1395
                first = false;
1192
1396
                authed = false;
 
1397
 
1193
1398
                out.clear();
1194
 
                from_net.clear();
1195
 
                bytesEncoded = 0;
1196
 
                pending_write = 0;
1197
 
                layer.reset();
 
1399
                out_pending = 0;
1198
1400
 
1199
1401
                if(mode >= ResetSessionAndData)
1200
1402
                {
 
1403
                        mech = QString();
 
1404
                        errorCode = (SASL::Error)-1;
 
1405
 
1201
1406
                        in.clear();
1202
1407
                        to_net.clear();
 
1408
                        from_net.clear();
 
1409
                        to_net_encoded = 0;
 
1410
                        layer.reset();
1203
1411
                }
1204
1412
 
1205
1413
                if(mode >= ResetAll)
1229
1437
        {
1230
1438
                c->setup(service, host, localSet ? &local : 0, remoteSet ? &remote : 0, ext_authid, ext_ssf);
1231
1439
                c->setConstraints(auth_flags, ssfmin, ssfmax);
 
1440
 
 
1441
                QString *p_username = 0;
 
1442
                QString *p_authzid = 0;
 
1443
                SecureArray *p_password = 0;
 
1444
                QString *p_realm = 0;
 
1445
 
 
1446
                if(set_username)
 
1447
                        p_username = &username;
 
1448
                if(set_authzid)
 
1449
                        p_authzid = &authzid;
 
1450
                if(set_password)
 
1451
                        p_password = &password;
 
1452
                if(set_realm)
 
1453
                        p_realm = &realm;
 
1454
 
 
1455
                c->setClientParams(p_username, p_authzid, p_password, p_realm);
1232
1456
        }
1233
1457
 
1234
1458
        void start()
1237
1461
                first = true;
1238
1462
 
1239
1463
                if(server)
 
1464
                {
 
1465
                        QCA_logTextMessage(QString("sasl[%1]: c->startServer()").arg(q->objectName()), Logger::Information);
1240
1466
                        c->startServer(server_realm, disableServerSendLast);
 
1467
                }
1241
1468
                else
 
1469
                {
 
1470
                        QCA_logTextMessage(QString("sasl[%1]: c->startClient()").arg(q->objectName()), Logger::Information);
1242
1471
                        c->startClient(mechlist, allowClientSendFirst);
 
1472
                }
1243
1473
        }
1244
1474
 
1245
1475
        void putServerFirstStep(const QString &mech, const QByteArray *clientInit)
1247
1477
                if(op != -1)
1248
1478
                        return;
1249
1479
 
 
1480
                QCA_logTextMessage(QString("sasl[%1]: c->serverFirstStep()").arg(q->objectName()), Logger::Information);
1250
1481
                op = OpServerFirstStep;
1251
 
 
1252
1482
                c->serverFirstStep(mech, clientInit);
1253
1483
        }
1254
1484
 
1257
1487
                if(op != -1)
1258
1488
                        return;
1259
1489
 
 
1490
                QCA_logTextMessage(QString("sasl[%1]: c->nextStep()").arg(q->objectName()), Logger::Information);
1260
1491
                op = OpNextStep;
1261
 
 
1262
1492
                c->nextStep(stepData);
1263
1493
        }
1264
1494
 
1267
1497
                if(op != -1)
1268
1498
                        return;
1269
1499
 
 
1500
                QCA_logTextMessage(QString("sasl[%1]: c->tryAgain()").arg(q->objectName()), Logger::Information);
1270
1501
                op = OpTryAgain;
1271
 
 
1272
1502
                c->tryAgain();
1273
1503
        }
1274
1504
 
 
1505
        void processNextAction()
 
1506
        {
 
1507
                if(actionQueue.isEmpty())
 
1508
                {
 
1509
                        if(need_update)
 
1510
                                update();
 
1511
                        return;
 
1512
                }
 
1513
 
 
1514
                Action a = actionQueue.takeFirst();
 
1515
 
 
1516
                // set up for the next one, if necessary
 
1517
                if(!actionQueue.isEmpty() || need_update)
 
1518
                {
 
1519
                        if(!actionTrigger.isActive())
 
1520
                                actionTrigger.start();
 
1521
                }
 
1522
 
 
1523
                if(a.type == Action::ClientStarted)
 
1524
                {
 
1525
                        emit q->clientStarted(a.haveInit, a.stepData);
 
1526
                }
 
1527
                else if(a.type == Action::NextStep)
 
1528
                {
 
1529
                        emit q->nextStep(a.stepData);
 
1530
                }
 
1531
                else if(a.type == Action::Authenticated)
 
1532
                {
 
1533
                        authed = true;
 
1534
 
 
1535
                        // write any app data waiting during authentication
 
1536
                        if(!out.isEmpty())
 
1537
                        {
 
1538
                                need_update = true;
 
1539
                                if(!actionTrigger.isActive())
 
1540
                                        actionTrigger.start();
 
1541
                        }
 
1542
 
 
1543
                        QCA_logTextMessage(QString("sasl[%1]: authenticated").arg(q->objectName()), Logger::Information);
 
1544
                        emit q->authenticated();
 
1545
                }
 
1546
                else if(a.type == Action::ReadyRead)
 
1547
                {
 
1548
                        emit q->readyRead();
 
1549
                }
 
1550
                else if(a.type == Action::ReadyReadOutgoing)
 
1551
                {
 
1552
                        emit q->readyReadOutgoing();
 
1553
                }
 
1554
        }
 
1555
 
1275
1556
        void update()
1276
1557
        {
 
1558
                // defer writes while authenticating
 
1559
                if(!authed)
 
1560
                {
 
1561
                        QCA_logTextMessage(QString("sasl[%1]: ignoring update while not yet authenticated").arg(q->objectName()), Logger::Information);
 
1562
                        return;
 
1563
                }
 
1564
 
 
1565
                if(!actionQueue.isEmpty())
 
1566
                {
 
1567
                        QCA_logTextMessage(QString("sasl[%1]: ignoring update while processing actions").arg(q->objectName()), Logger::Information);
 
1568
                        need_update = true;
 
1569
                        return;
 
1570
                }
 
1571
 
 
1572
                // only allow one operation at a time
1277
1573
                if(op != -1)
 
1574
                {
 
1575
                        QCA_logTextMessage(QString("sasl[%1]: ignoring update while operation active").arg(q->objectName()), Logger::Information);
1278
1576
                        return;
1279
 
 
 
1577
                }
 
1578
 
 
1579
                need_update = false;
 
1580
 
 
1581
                QCA_logTextMessage(QString("sasl[%1]: c->update()").arg(q->objectName()), Logger::Information);
1280
1582
                op = OpUpdate;
1281
 
 
1282
 
                pending_write += out.size();
 
1583
                out_pending += out.size();
1283
1584
                c->update(from_net, out);
1284
1585
                from_net.clear();
1285
1586
                out.clear();
1288
1589
private slots:
1289
1590
        void sasl_resultsReady()
1290
1591
        {
1291
 
                QPointer<QObject> self = this;
 
1592
                QCA_logTextMessage(QString("sasl[%1]: c->resultsReady()").arg(q->objectName()), Logger::Information);
1292
1593
 
1293
1594
                int last_op = op;
1294
1595
                op = -1;
1297
1598
 
1298
1599
                if(last_op == OpStart)
1299
1600
                {
 
1601
                        mech = c->mech();
 
1602
 
1300
1603
                        if(server)
1301
1604
                        {
1302
1605
                                if(r != SASLContext::Success)
1342
1645
                                }
1343
1646
                                else if(r == SASLContext::Success)
1344
1647
                                {
1345
 
                                        // FIXME: not signal safe
1346
 
                                        emit q->nextStep(c->stepData());
1347
 
 
1348
 
                                        authed = true;
1349
 
                                        emit q->authenticated();
 
1648
                                        if(!disableServerSendLast)
 
1649
                                                actionQueue += Action(Action::NextStep, c->stepData());
 
1650
 
 
1651
                                        actionQueue += Action(Action::Authenticated);
 
1652
 
 
1653
                                        processNextAction();
1350
1654
                                        return;
1351
1655
                                }
1352
1656
                                else // error
1377
1681
                                        }
1378
1682
 
1379
1683
                                        first = false;
1380
 
                                        emit q->clientStarted(c->haveClientInit(), c->stepData());
 
1684
                                        actionQueue += Action(Action::ClientStarted, c->haveClientInit(), c->stepData());
 
1685
                                        if(r == SASLContext::Success)
 
1686
                                                actionQueue += Action(Action::Authenticated);
 
1687
 
 
1688
                                        processNextAction();
1381
1689
                                        return;
1382
1690
                                }
1383
1691
                                else
1401
1709
                                        }
1402
1710
                                        else if(r == SASLContext::Success)
1403
1711
                                        {
1404
 
                                                // FIXME: not signal safe
1405
 
                                                emit q->nextStep(c->stepData());
 
1712
                                                actionQueue += Action(Action::NextStep, c->stepData());
 
1713
                                                actionQueue += Action(Action::Authenticated);
1406
1714
 
1407
 
                                                authed = true;
1408
 
                                                emit q->authenticated();
 
1715
                                                processNextAction();
1409
1716
                                                return;
1410
1717
                                        }
1411
1718
                                }
1420
1727
                                return;
1421
1728
                        }
1422
1729
 
1423
 
                        QByteArray a = c->to_net();
1424
 
                        QByteArray b = c->to_app();
1425
 
                        int enc = c->encoded();
1426
 
 
1427
 
                        to_net += a;
1428
 
                        in += b;
1429
 
 
1430
 
                        bool more = false;
1431
 
                        pending_write -= enc;
1432
 
                        if(pending_write > 0)
1433
 
                                more = true;
1434
 
                        bytesEncoded += enc;
1435
 
 
1436
 
                        if(!a.isEmpty())
1437
 
                        {
1438
 
                                emit q->readyReadOutgoing();
1439
 
                                if(!self)
1440
 
                                        return;
1441
 
                        }
1442
 
 
1443
 
                        if(!b.isEmpty())
1444
 
                        {
1445
 
                                emit q->readyRead();
1446
 
                                if(!self)
1447
 
                                        return;
1448
 
                        }
1449
 
 
1450
 
                        if(more)
 
1730
                        QByteArray c_to_net = c->to_net();
 
1731
                        QByteArray c_to_app = c->to_app();
 
1732
                        int enc = -1;
 
1733
                        if(!c_to_net.isEmpty())
 
1734
                                enc = c->encoded();
 
1735
 
 
1736
                        bool io_pending = false;
 
1737
                        if(!c_to_net.isEmpty())
 
1738
                                out_pending -= enc;
 
1739
 
 
1740
                        if(out_pending > 0)
 
1741
                                io_pending = true;
 
1742
 
 
1743
                        if(!out.isEmpty())
 
1744
                                io_pending = true;
 
1745
 
 
1746
                        to_net += c_to_net;
 
1747
                        in += c_to_app;
 
1748
                        to_net_encoded += enc;
 
1749
 
 
1750
                        if(!c_to_net.isEmpty())
 
1751
                                actionQueue += Action(Action::ReadyReadOutgoing);
 
1752
 
 
1753
                        if(!c_to_app.isEmpty())
 
1754
                                actionQueue += Action(Action::ReadyRead);
 
1755
 
 
1756
                        if(io_pending)
1451
1757
                                update();
 
1758
 
 
1759
                        processNextAction();
 
1760
                        return;
1452
1761
                }
1453
1762
        }
 
1763
 
 
1764
        void doNextAction()
 
1765
        {
 
1766
                processNextAction();
 
1767
        }
1454
1768
};
1455
1769
 
1456
1770
SASL::SASL(QObject *parent, const QString &provider)
1482
1796
void SASL::setConstraints(AuthFlags f, SecurityLevel s)
1483
1797
{
1484
1798
        int min = 0;
1485
 
        if (s == SL_Integrity)
 
1799
        if(s == SL_Integrity)
1486
1800
                min = 1;
1487
 
        else if (s == SL_Export)
 
1801
        else if(s == SL_Export)
1488
1802
                min = 56;
1489
 
        else if (s == SL_Baseline)
 
1803
        else if(s == SL_Baseline)
1490
1804
                min = 128;
1491
 
        else if (s == SL_High)
 
1805
        else if(s == SL_High)
1492
1806
                min = 192;
1493
 
        else if (s == SL_Highest)
 
1807
        else if(s == SL_Highest)
1494
1808
                min = 256;
1495
1809
 
1496
1810
        setConstraints(f, min, 256);
1603
1917
 
1604
1918
QString SASL::mechanism() const
1605
1919
{
1606
 
        return d->c->mech();
 
1920
        return d->mech;
1607
1921
}
1608
1922
 
1609
1923
QStringList SASL::mechanismList() const
1656
1970
        QByteArray a = d->to_net;
1657
1971
        d->to_net.clear();
1658
1972
        if(plainBytes)
1659
 
                *plainBytes = d->bytesEncoded;
1660
 
        d->layer.specifyEncoded(a.size(), d->bytesEncoded);
1661
 
        d->bytesEncoded = 0;
 
1973
                *plainBytes = d->to_net_encoded;
 
1974
        d->layer.specifyEncoded(a.size(), d->to_net_encoded);
 
1975
        d->to_net_encoded = 0;
1662
1976
        return a;
1663
1977
}
1664
1978