File indexing completed on 2024-04-28 04:58:02

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2000 Caldera Systems Inc.
0004     SPDX-FileCopyrightText: 2020 Harald Sitter <sitter@kde.org>
0005     SPDX-FileContributor: Matthew Peterson <mpeterson@caldera.com>
0006 */
0007 
0008 #include "smbcontext.h"
0009 
0010 #include <KConfig>
0011 #include <KConfigGroup>
0012 
0013 #include "smb-logsettings.h"
0014 #include "smbauthenticator.h"
0015 
0016 SMBContext::SMBContext(SMBAuthenticator *authenticator)
0017     : m_context(smbc_new_context(), &freeContext)
0018     , m_authenticator(authenticator)
0019 {
0020     Q_ASSERT(m_context);
0021     if (!m_context) {
0022         return;
0023     }
0024 
0025     qCDebug(KIO_SMB_LOG) << "auth_initialize_smbc";
0026 
0027     KConfig cfg("kioslaverc", KConfig::SimpleConfig);
0028     int debugLevel = cfg.group("SMB").readEntry("DebugLevel", 0);
0029     qCDebug(KIO_SMB_LOG) << "Setting debug level to:" << debugLevel;
0030 
0031 #ifdef DEPRECATED_SMBC_INTERFACE // defined by libsmbclient.h of Samba 3.2
0032     smbc_setOptionUserData(m_context.get(), this);
0033     smbc_setFunctionAuthDataWithContext(m_context.get(), auth_cb);
0034 
0035     /* New libsmbclient interface of Samba 3.2 */
0036     smbc_setDebug(m_context.get(), debugLevel);
0037 
0038     /* Enable Kerberos support */
0039     smbc_setOptionUseKerberos(m_context.get(), 1);
0040     smbc_setOptionFallbackAfterKerberos(m_context.get(), 1);
0041 #else
0042     smbc_option_set(m_context.get(), "user_data", this);
0043     m_context->callbacks.auth_fn = NULL;
0044     smbc_option_set(m_context.get(), "auth_function", (void *)auth_cb);
0045 
0046     m_context->debug = debug_level;
0047 
0048 #if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS)
0049     m_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS;
0050 #endif
0051 #endif /* DEPRECATED_SMBC_INTERFACE */
0052 
0053     if (!smbc_init_context(m_context.get())) {
0054         m_context.reset();
0055         return;
0056     }
0057 
0058     smbc_set_context(m_context.get());
0059 
0060     // TODO: refactor; checkPassword should query this on
0061     // demand to not run into situations where we may have cached
0062     // the workgroup early on and it changed since. Needs context
0063     // being held in the worker though, which opens us up to nullptr
0064     // problems should checkPassword be called without init first.
0065     authenticator->setDefaultWorkgroup(smbc_getWorkgroup(*this));
0066 
0067     return;
0068 }
0069 
0070 bool SMBContext::isValid() const
0071 {
0072     return smbcctx() && authenticator();
0073 }
0074 
0075 void SMBContext::auth_cb(SMBCCTX *context,
0076                          const char *server,
0077                          const char *share,
0078                          char *workgroup,
0079                          int wgmaxlen,
0080                          char *username,
0081                          int unmaxlen,
0082                          char *password,
0083                          int pwmaxlen)
0084 {
0085     // Unfortunately because the callback API doesn't support callback specific user_data we need
0086     // to route all auths through our context object otherwise the authenticator would have
0087     // to twiddle the global context user_data and that seems much worse :|
0088     if (context != nullptr) {
0089 #ifdef DEPRECATED_SMBC_INTERFACE
0090         auto *that = static_cast<SMBContext *>(smbc_getOptionUserData(context));
0091 #else
0092         auto *that = static_cast<SMBCContext *>(smbc_option_get(context, "user_data"));
0093 #endif
0094         that->m_authenticator->auth(context, server, share, workgroup, wgmaxlen, username, unmaxlen, password, pwmaxlen);
0095     }
0096 }
0097 
0098 void SMBContext::freeContext(SMBCCTX *ptr)
0099 {
0100     smbc_free_context(ptr, 1);
0101 }