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