File indexing completed on 2024-12-15 04:50:15

0001 /*
0002   This file is part of libkldap.
0003   SPDX-FileCopyrightText: 2004-2006 Szombathelyi György <gyurco@freemail.hu>
0004 
0005   SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "ber.h"
0009 #include "kldap_config.h"
0010 
0011 #include "ldap_core_debug.h"
0012 
0013 #include <QList>
0014 #include <QVarLengthArray>
0015 
0016 #include <cstdarg>
0017 
0018 #if LDAP_FOUND
0019 
0020 #ifdef Q_OS_SOLARIS // krazy:exclude=cpp
0021 #define BC31 1
0022 #endif
0023 
0024 #if !HAVE_WINLDAP_H
0025 #include <lber.h>
0026 #include <ldap.h>
0027 #else
0028 #include "w32-ldap-help.h"
0029 #endif
0030 
0031 #ifndef LBER_USE_DER
0032 #define LBER_USE_DER 1
0033 #endif
0034 
0035 #if !HAVE_BER_MEMFREE
0036 #if !HAVE_WINLDAP_H
0037 #define ber_memfree(x) ldap_memfree(x)
0038 #else
0039 #define ber_memfree(x) win_ldap_memfree(x)
0040 #endif
0041 #endif
0042 
0043 #endif
0044 
0045 using namespace KLDAPCore;
0046 
0047 class Q_DECL_HIDDEN Ber::BerPrivate
0048 {
0049 public:
0050 #if LDAP_FOUND
0051     BerElement *mBer = nullptr;
0052 #endif
0053 };
0054 
0055 #if LDAP_FOUND
0056 Ber::Ber()
0057     : d(new BerPrivate)
0058 {
0059     d->mBer = ber_alloc_t(LBER_USE_DER);
0060     Q_ASSERT(d->mBer);
0061 }
0062 
0063 Ber::Ber(const QByteArray &value)
0064     : d(new BerPrivate)
0065 {
0066     struct berval bv;
0067     bv.bv_val = (char *)value.data();
0068     bv.bv_len = value.size();
0069     d->mBer = ber_init(&bv);
0070     Q_ASSERT(d->mBer);
0071 }
0072 
0073 Ber::~Ber()
0074 {
0075     ber_free(d->mBer, 1);
0076 }
0077 
0078 Ber::Ber(const Ber &that)
0079     : d(new BerPrivate)
0080 {
0081     struct berval *bv;
0082     if (ber_flatten(that.d->mBer, &bv) == 0) {
0083         d->mBer = ber_init(bv);
0084         ber_bvfree(bv);
0085     }
0086 }
0087 
0088 Ber &Ber::operator=(const Ber &that)
0089 {
0090     if (this == &that) {
0091         return *this;
0092     }
0093 
0094     struct berval *bv;
0095     if (ber_flatten(that.d->mBer, &bv) == 0) {
0096         d->mBer = ber_init(bv);
0097         ber_bvfree(bv);
0098     }
0099     return *this;
0100 }
0101 
0102 QByteArray Ber::flatten() const
0103 {
0104     QByteArray ret;
0105     struct berval *bv;
0106     if (ber_flatten(d->mBer, &bv) == 0) {
0107         ret = QByteArray(bv->bv_val, bv->bv_len);
0108         ber_bvfree(bv);
0109     }
0110     return ret;
0111 }
0112 
0113 int Ber::printf(QString format, ...)
0114 {
0115     char fmt[2];
0116     va_list args;
0117     va_start(args, format);
0118     fmt[1] = '\0';
0119 
0120     int i = 0;
0121     int ret = 0;
0122     while (i < format.length()) {
0123         fmt[0] = format[i].toLatin1();
0124         i++;
0125         switch (fmt[0]) {
0126         case 'b':
0127         case 'e':
0128         case 'i': {
0129             ber_int_t v = va_arg(args, int);
0130             ret = ber_printf(d->mBer, fmt, v);
0131             break;
0132         }
0133         case 'B': {
0134             // FIXME: QBitArray would be logical, but how to access the bits?
0135             QByteArray *B = va_arg(args, QByteArray *);
0136             int Bc = va_arg(args, int);
0137             ret = ber_printf(d->mBer, fmt, B->data(), Bc);
0138             break;
0139         }
0140         case 'o': {
0141             QByteArray *o = va_arg(args, QByteArray *);
0142             ret = ber_printf(d->mBer, fmt, o->data(), o->size());
0143             break;
0144         }
0145         case 'O': {
0146             QByteArray *O = va_arg(args, QByteArray *);
0147             struct berval bv;
0148             bv.bv_val = (char *)O->data();
0149             bv.bv_len = O->size();
0150             ret = ber_printf(d->mBer, fmt, &bv);
0151             break;
0152         }
0153         case 's': {
0154             QByteArray *s = va_arg(args, QByteArray *);
0155             ret = ber_printf(d->mBer, fmt, s->data());
0156             break;
0157             break;
0158         }
0159         case 't': {
0160             unsigned int t = va_arg(args, unsigned int);
0161             ret = ber_printf(d->mBer, fmt, t);
0162             break;
0163         }
0164         case 'v': {
0165             QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
0166             QVarLengthArray<const char *> l(v->count() + 1);
0167             int j;
0168             for (j = 0; j < v->count(); j++) {
0169                 l[j] = v->at(j).data();
0170             }
0171             l[j] = nullptr;
0172             ret = ber_printf(d->mBer, fmt, l.data());
0173             break;
0174         }
0175         case 'V': {
0176             QList<QByteArray> *V = va_arg(args, QList<QByteArray> *);
0177             QVarLengthArray<struct berval *> bv(V->count() + 1);
0178             QVarLengthArray<struct berval> bvs(V->count());
0179             int j;
0180             for (j = 0; j < V->count(); j++) {
0181                 bvs[j].bv_val = (char *)V->at(j).data();
0182                 bvs[j].bv_len = V->at(j).size();
0183                 bv[j] = &bvs[j];
0184             }
0185             bv[V->count()] = nullptr;
0186             ret = ber_printf(d->mBer, fmt, bv.data());
0187             break;
0188         }
0189         case 'n':
0190         case '{':
0191         case '}':
0192         case '[':
0193         case ']':
0194             ret = ber_printf(d->mBer, fmt);
0195             break;
0196         default:
0197             qCWarning(LDAP_LOG) << "Invalid BER format parameter: '" << fmt << "'";
0198             ret = -1;
0199         }
0200         qCDebug(LDAP_LOG) << "ber_printf format:" << fmt << "ret:" << ret;
0201         if (ret == -1) {
0202             break;
0203         }
0204     }
0205     va_end(args);
0206     return ret;
0207 }
0208 
0209 int Ber::scanf(QString format, ...)
0210 {
0211     char fmt[2];
0212     va_list args;
0213     va_start(args, format);
0214     fmt[1] = '\0';
0215 
0216     int i = 0;
0217     int ret = 0;
0218     while (i < format.length()) {
0219         fmt[0] = format[i].toLatin1();
0220         i++;
0221         switch (fmt[0]) {
0222         case 'l':
0223         case 'b':
0224         case 'e':
0225         case 'i': {
0226             int *v = va_arg(args, int *);
0227             ret = ber_scanf(d->mBer, fmt, v);
0228             break;
0229         }
0230         case 'B': {
0231             // FIXME: QBitArray would be logical, but how to access the bits?
0232             QByteArray *B = va_arg(args, QByteArray *);
0233             int *Bc = va_arg(args, int *);
0234             char *c;
0235             ret = ber_scanf(d->mBer, fmt, &c, Bc);
0236             if (ret != -1) {
0237                 *B = QByteArray(c, (*Bc + 7) / 8);
0238                 ber_memfree(c);
0239             }
0240             break;
0241         }
0242         case 'o': {
0243             QByteArray *o = va_arg(args, QByteArray *);
0244             struct berval bv;
0245             ret = ber_scanf(d->mBer, fmt, &bv);
0246             if (ret != -1) {
0247                 *o = QByteArray(bv.bv_val, bv.bv_len);
0248                 ber_memfree(bv.bv_val);
0249             }
0250             break;
0251         }
0252         case 'O': {
0253             QByteArray *O = va_arg(args, QByteArray *);
0254             struct berval *bv;
0255             ret = ber_scanf(d->mBer, fmt, &bv);
0256             if (ret != -1) {
0257                 *O = QByteArray(bv->bv_val, bv->bv_len);
0258                 ber_bvfree(bv);
0259             }
0260             break;
0261         }
0262         case 'm': { // the same as 'O', just *bv should not be freed.
0263             QByteArray *m = va_arg(args, QByteArray *);
0264             struct berval *bv;
0265             ret = ber_scanf(d->mBer, fmt, &bv);
0266             if (ret != -1) {
0267                 *m = QByteArray(bv->bv_val, bv->bv_len);
0268             }
0269             break;
0270         }
0271         case 'a': {
0272             QByteArray *a = va_arg(args, QByteArray *);
0273             char *c;
0274             ret = ber_scanf(d->mBer, fmt, &c);
0275             if (ret != -1) {
0276                 *a = QByteArray(c);
0277                 ber_memfree(c);
0278             }
0279             break;
0280         }
0281 
0282         case 's': {
0283             QByteArray *s = va_arg(args, QByteArray *);
0284             char buf[255];
0285             ber_len_t l = sizeof(buf);
0286             ret = ber_scanf(d->mBer, fmt, &buf, &l);
0287             if (ret != -1) {
0288                 *s = QByteArray(buf, l);
0289             }
0290             break;
0291         }
0292         case 't':
0293         case 'T': {
0294             unsigned int *t = va_arg(args, unsigned int *);
0295             ret = ber_scanf(d->mBer, fmt, t);
0296             break;
0297         }
0298         case 'v': {
0299             QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
0300             char **c;
0301             char **c2;
0302             ret = ber_scanf(d->mBer, fmt, &c);
0303             if (ret != -1 && c) {
0304                 c2 = c;
0305                 while (*c) {
0306                     v->append(QByteArray(*c));
0307                     ber_memfree(*c);
0308                     c++;
0309                 }
0310                 ber_memfree((char *)c2);
0311             }
0312             break;
0313         }
0314         case 'V': {
0315             QList<QByteArray> *v = va_arg(args, QList<QByteArray> *);
0316             struct berval **bv;
0317             struct berval **bv2;
0318             ret = ber_scanf(d->mBer, fmt, &bv);
0319             if (ret != -1 && bv) {
0320                 bv2 = bv;
0321                 while (*bv) {
0322                     v->append(QByteArray((*bv)->bv_val, (*bv)->bv_len));
0323                     bv++;
0324                 }
0325                 ber_bvecfree(bv2);
0326             }
0327             break;
0328         }
0329         case 'x':
0330         case 'n':
0331         case '{':
0332         case '}':
0333         case '[':
0334         case ']':
0335             ret = ber_scanf(d->mBer, fmt);
0336             break;
0337         default:
0338             qCWarning(LDAP_LOG) << "Invalid BER format parameter: '" << fmt << "'";
0339             ret = -1;
0340         }
0341 
0342         qCDebug(LDAP_LOG) << "ber_scanf format:" << fmt << "ret:" << ret;
0343         if (ret == -1) {
0344             break;
0345         }
0346     }
0347     va_end(args);
0348     return ret;
0349 }
0350 
0351 unsigned int Ber::peekTag(int &size)
0352 {
0353     unsigned int ret;
0354     ber_len_t len;
0355     ret = ber_peek_tag(d->mBer, &len);
0356     size = len;
0357     return ret;
0358 }
0359 
0360 unsigned int Ber::skipTag(int &size)
0361 {
0362     unsigned int ret;
0363     ber_len_t len;
0364     ret = ber_skip_tag(d->mBer, &len);
0365     size = len;
0366     return ret;
0367 }
0368 
0369 #else
0370 
0371 Ber::Ber()
0372     : d(new BerPrivate)
0373 {
0374     qCritical() << "LDAP support not compiled";
0375 }
0376 
0377 Ber::Ber(const QByteArray &)
0378     : d(new BerPrivate)
0379 {
0380     qCritical() << "LDAP support not compiled";
0381 }
0382 
0383 Ber::~Ber()
0384 {
0385 }
0386 
0387 Ber::Ber(const Ber &)
0388     : d(new BerPrivate)
0389 {
0390     qCritical() << "LDAP support not compiled";
0391 }
0392 
0393 Ber &Ber::operator=(const Ber &that)
0394 {
0395     if (this == &that) {
0396         return *this;
0397     }
0398     qCritical() << "LDAP support not compiled";
0399     return *this;
0400 }
0401 
0402 QByteArray Ber::flatten() const
0403 {
0404     qCritical() << "LDAP support not compiled";
0405     return QByteArray();
0406 }
0407 
0408 int Ber::printf(QString format, ...)
0409 {
0410     Q_UNUSED(format)
0411     qCritical() << "LDAP support not compiled";
0412     return -1;
0413 }
0414 
0415 int Ber::scanf(QString format, ...)
0416 {
0417     Q_UNUSED(format)
0418     qCritical() << "LDAP support not compiled";
0419     return -1;
0420 }
0421 
0422 unsigned int Ber::peekTag(int &size)
0423 {
0424     Q_UNUSED(size)
0425     qCritical() << "LDAP support not compiled";
0426     return 0;
0427 }
0428 
0429 unsigned int Ber::skipTag(int &size)
0430 {
0431     Q_UNUSED(size)
0432     qCritical() << "LDAP support not compiled";
0433     return 0;
0434 }
0435 
0436 #endif