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

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2000 Caldera Systems Inc.
0004     SPDX-FileCopyrightText: 2021-2022 Harald Sitter <sitter@kde.org>
0005     SPDX-FileContributor: Matthew Peterson <mpeterson@caldera.com>
0006 */
0007 
0008 #ifndef KIO_SMB_H_INCLUDED
0009 #define KIO_SMB_H_INCLUDED
0010 
0011 #include <config-smb.h>
0012 
0013 #include "smb-logsettings.h"
0014 
0015 //--------------
0016 // KF includes
0017 //--------------
0018 #include <KIO/Global>
0019 #include <KIO/WorkerBase>
0020 
0021 //-----------------------------
0022 // Standard C library includes
0023 //-----------------------------
0024 #include <arpa/inet.h>
0025 #include <errno.h>
0026 #include <net/if.h>
0027 #include <netinet/in.h>
0028 #include <stdio.h>
0029 #include <stdlib.h>
0030 #include <sys/ioctl.h>
0031 #include <sys/socket.h>
0032 #include <sys/stat.h>
0033 #include <time.h>
0034 
0035 //-----------------------------
0036 // Qt includes
0037 //-----------------------------
0038 
0039 #include <QDateTime>
0040 #include <QLoggingCategory>
0041 #include <QObject>
0042 #include <QUrl>
0043 
0044 //-------------------------------
0045 // Samba client library includes
0046 //-------------------------------
0047 extern "C" {
0048 #include <libsmbclient.h>
0049 }
0050 
0051 //---------------------------
0052 // kio_smb internal includes
0053 //---------------------------
0054 #include "smbauthenticator.h"
0055 #include "smbcontext.h"
0056 #include "smburl.h"
0057 
0058 using namespace KIO;
0059 class SMBWorker;
0060 
0061 class WorkerFrontend : public SMBAbstractFrontend
0062 {
0063 public:
0064     explicit WorkerFrontend(SMBWorker &worker);
0065     bool checkCachedAuthentication(AuthInfo &info) override;
0066 
0067 private:
0068     SMBWorker &m_worker;
0069 };
0070 
0071 class SMBWorker : public QObject, public KIO::WorkerBase
0072 {
0073     Q_OBJECT
0074     friend class SMBCDiscoverer;
0075     friend class SMBResumeIO;
0076     WorkerFrontend m_frontend{*this};
0077     SMBContext m_context{new SMBAuthenticator(m_frontend)};
0078     Q_DISABLE_COPY(SMBWorker)
0079 
0080 private:
0081     class SMBError
0082     {
0083     public:
0084         int kioErrorId;
0085         QString errorString;
0086     };
0087 
0088     /**
0089      * we store the current url, it's needed for
0090      * callback authorization method
0091      */
0092     SMBUrl m_current_url;
0093 
0094     /**
0095      * From Controlcenter, show SHARE$ or not
0096      */
0097     //    bool m_showHiddenShares;     //currently unused, Alex <neundorf@kde.org>
0098 
0099     /**
0100      * libsmbclient need global variables to store in,
0101      * else it crashes on exit next method after use cache_stat,
0102      * looks like gcc (C/C++) failure
0103      */
0104     struct stat st {
0105     };
0106 
0107 protected:
0108     //---------------------------------------------
0109     // Authentication functions (kio_smb_auth.cpp)
0110     //---------------------------------------------
0111     // (please prefix functions with auth)
0112 
0113     /**
0114      * Description :   Initializes the libsmbclient
0115      * Return :        true on success false with errno set on error
0116      */
0117     bool auth_initialize_smbc();
0118 
0119     int checkPassword(SMBUrl &url);
0120 
0121     //---------------------------------------------
0122     // Cache functions (kio_smb_auth.cpp)
0123     //---------------------------------------------
0124 
0125     // Stat methods
0126 
0127     //-----------------------------------------
0128     // Browsing functions (kio_smb_browse.cpp)
0129     //-----------------------------------------
0130     // (please prefix functions with browse)
0131 
0132     /**
0133      * Description :  Return a stat of given SMBUrl. Calls cache_stat and
0134      *                pack it in UDSEntry. UDSEntry will not be cleared
0135      * Parameter :    SMBUrl the url to stat
0136      * Return :       cache_stat() return code
0137      */
0138     int browse_stat_path(const SMBUrl &url, UDSEntry &udsentry);
0139 
0140     /**
0141      * Description :  call smbc_stat and return stats of the url
0142      * Parameter :    SMBUrl the url to stat
0143      * Return :       stat* of the url
0144      * Note :         it has some problems with stat in method, looks like
0145      *                something leave(or removed) on the stack. If your
0146      *                method segfault on returning try to change the stat*
0147      *                variable
0148      */
0149     static int cache_stat(const SMBUrl &url, struct stat *st);
0150 
0151     //---------------------------------------------
0152     // Configuration functions (kio_smb_config.cpp)
0153     //---------------------------------------------
0154     // (please prefix functions with config)
0155 
0156     //---------------------------------------
0157     // Directory functions (kio_smb_dir.cpp)
0158     //---------------------------------------
0159     // (please prefix functions with dir)
0160 
0161     //--------------------------------------
0162     // File IO functions (kio_smb_file.cpp)
0163     //--------------------------------------
0164     // (please prefix functions with file)
0165 
0166     //----------------------------
0167     // Misc functions (this file)
0168     //----------------------------
0169 
0170     /**
0171      * Description :  correct a given URL
0172      *                valid URL's are
0173      *
0174      *                smb://[[domain;]user[:password]@]server[:port][/share[/path[/file]]]
0175      *                smb:/[[domain;]user[:password]@][group/[server[/share[/path[/file]]]]]
0176      *                domain   = workgroup(domain) of the user
0177      *                user     = username
0178      *                password = password of useraccount
0179      *                group    = workgroup(domain) of server
0180      *                server   = host to connect
0181      *                share    = a share of the server (host)
0182      *                path     = a path of the share
0183      * Parameter :    QUrl the url to check
0184      * Return :       new QUrl if it is corrected. else the same QUrl
0185      */
0186     QUrl checkURL(const QUrl &kurl) const;
0187 
0188     Q_REQUIRED_RESULT WorkerResult reportError(const SMBUrl &url, const int errNum);
0189     void reportWarning(const SMBUrl &url, const int errNum);
0190 
0191 public:
0192     // Functions overwritten in kio_smb.cpp
0193     SMBWorker(const QByteArray &pool, const QByteArray &app);
0194     ~SMBWorker() override = default;
0195 
0196     // Functions overwritten in kio_smb_browse.cpp
0197     Q_REQUIRED_RESULT WorkerResult listDir(const QUrl &url) override;
0198     Q_REQUIRED_RESULT WorkerResult stat(const QUrl &url) override;
0199 
0200     // Functions overwritten in kio_smb_config.cpp
0201     void reparseConfiguration() override;
0202 
0203     // Functions overwritten in kio_smb_dir.cpp
0204     Q_REQUIRED_RESULT WorkerResult copy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags) override;
0205     Q_REQUIRED_RESULT WorkerResult del(const QUrl &kurl, bool isfile) override;
0206     Q_REQUIRED_RESULT WorkerResult mkdir(const QUrl &kurl, int permissions) override;
0207     Q_REQUIRED_RESULT WorkerResult rename(const QUrl &src, const QUrl &dest, KIO::JobFlags flags) override;
0208 
0209     // Functions overwritten in kio_smb_file.cpp
0210     Q_REQUIRED_RESULT WorkerResult get(const QUrl &kurl) override;
0211     Q_REQUIRED_RESULT WorkerResult put(const QUrl &kurl, int permissions, KIO::JobFlags flags) override;
0212     Q_REQUIRED_RESULT WorkerResult open(const QUrl &kurl, QIODevice::OpenMode mode) override;
0213     Q_REQUIRED_RESULT WorkerResult read(KIO::filesize_t bytesRequested) override;
0214     Q_REQUIRED_RESULT WorkerResult write(const QByteArray &fileData) override;
0215     Q_REQUIRED_RESULT WorkerResult seek(KIO::filesize_t offset) override;
0216     Q_REQUIRED_RESULT WorkerResult truncate(KIO::filesize_t size) override;
0217     Q_REQUIRED_RESULT WorkerResult close() override;
0218     Q_REQUIRED_RESULT WorkerResult fileSystemFreeSpace(const QUrl &url) override;
0219     Q_REQUIRED_RESULT WorkerResult special(const QByteArray &) override;
0220 
0221 private:
0222     SMBError errnumToKioError(const SMBUrl &url, const int errNum);
0223     Q_REQUIRED_RESULT WorkerResult smbCopy(const QUrl &src, const QUrl &dst, int permissions, KIO::JobFlags flags);
0224     Q_REQUIRED_RESULT WorkerResult smbCopyGet(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags);
0225     Q_REQUIRED_RESULT WorkerResult smbCopyPut(const QUrl &ksrc, const QUrl &kdst, int permissions, KIO::JobFlags flags);
0226     bool workaroundEEXIST(const int errNum) const;
0227     int statToUDSEntry(const QUrl &url, const struct stat &st, KIO::UDSEntry &udsentry);
0228     Q_REQUIRED_RESULT WorkerResult getACE(QDataStream &stream);
0229     Q_REQUIRED_RESULT WorkerResult setACE(QDataStream &stream);
0230 
0231     /**
0232      * Used in open(), read(), write(), and close()
0233      * FIXME Placing these in the private section above causes m_openUrl = kurl
0234      * to fail in SMBWorker::open. Need to find out why this is.
0235      */
0236     int m_openFd;
0237     SMBUrl m_openUrl;
0238 
0239     const bool m_enableEEXISTWorkaround; /* Enables a workaround for some broken libsmbclient versions */
0240     // Close without calling finish(). Use this to close after error.
0241     void closeWithoutFinish();
0242 
0243     // Apply mtime if modified metadata is set. This callsback with a utbuf
0244     // with modtime accordingly set. The callback should implement the actual apply.
0245     template<typename UTimeFunction>
0246     void applyMTime(UTimeFunction &&callback)
0247     {
0248         const QString mtimeStr = metaData("modified");
0249         if (mtimeStr.isEmpty()) {
0250             return;
0251         }
0252         qCDebug(KIO_SMB_LOG) << "modified:" << mtimeStr;
0253 
0254         const QDateTime dateTime = QDateTime::fromString(mtimeStr, Qt::ISODate);
0255         if (dateTime.isValid()) {
0256             struct utimbuf utbuf {
0257             };
0258             utbuf.modtime = dateTime.toSecsSinceEpoch(); // modification time
0259             callback(utbuf);
0260         }
0261     }
0262 
0263     void applyMTimeSMBC(const SMBUrl &url)
0264     {
0265 #ifdef HAVE_UTIME_H // smbc_utime is conditional inside the libsmb headers
0266         applyMTime([url](struct utimbuf utbuf) {
0267             struct stat st {
0268             };
0269             if (cache_stat(url, &st) == 0) {
0270                 utbuf.actime = st.st_atime; // access time, unchanged
0271                 smbc_utime(url.toSmbcUrl(), &utbuf);
0272             }
0273         });
0274 #endif
0275     }
0276 };
0277 
0278 //===========================================================================
0279 // Main worker entrypoint (see kio_smb.cpp)
0280 extern "C" {
0281 int kdemain(int argc, char **argv);
0282 }
0283 
0284 #endif // #endif KIO_SMB_H_INCLUDED