📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
細 文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag… |
|||
| (同じ利用者による、間の29版が非表示) | |||
| 2行目: | 2行目: | ||
Qtにおいて、簡潔にSSH接続を確立する手順を記載する。<br> | Qtにおいて、簡潔にSSH接続を確立する手順を記載する。<br> | ||
<br> | <br> | ||
* | * libSSHライブラリ (LGPLライセンス) を使用する。 | ||
* | * libSSH2ライブラリ (3条項BSDライセンス) を使用する。 | ||
* | * <code>QProcess</code>クラスを使用して、外部のSSHプロセスをフォークして接続を確立する。 | ||
* wolfSSH | |||
*: wolfSSHライブラリは、wolfSSLと連携して使用する。 | |||
*: 無償版は、<u>GPL v2ライセンス</u>である。 | |||
*: 有償版は、独自ライセンスである。 | |||
*: https://wolfssl.jp/products/wolfssh/ | |||
*: Github : https://github.com/wolfSSL/wolfssh | |||
*: wolfSSLのGithub : https://github.com/wolfSSL/wolfssl | |||
*: <br> | |||
*: また、wolfSSLは、IoTデバイス、組み込み向け小型デバイスにも対応した軽量のSSL/TLSライブラリである。 | |||
* QSshライブラリを使用する。 | |||
*: QSshは、QtアプリケーションにSSHとSFTPのサポートを提供する。 | |||
*: QSshプロジェクトは、過去のQt CreatorのSSHプラグインに基づいており、全てのクレジットはQt Creatorチームに帰属する。 | |||
*: ただし、現在では、Qt CreatorはOpenSSHを使用している。 | |||
*: <br> | |||
*: https://github.com/sandsmark/QSsh | |||
<br><br> | <br><br> | ||
| 192行目: | 207行目: | ||
#include <libssh/libssh.h> | #include <libssh/libssh.h> | ||
int VerifyKnownsHost(ssh_session | int VerifyKnownsHost(ssh_session my_ssh_session, QString &strErrMsg); | ||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||
| 199行目: | 214行目: | ||
// SSHセッションの作成 | // SSHセッションの作成 | ||
ssh_session | ssh_session my_ssh_session = ssh_new(); | ||
if (my_ssh_session == NULL) { | if (my_ssh_session == NULL) { | ||
// 作成に失敗した場合 | // 作成に失敗した場合 | ||
| 210行目: | 225行目: | ||
QString port = "<SSHポート番号 例: 22>"; | QString port = "<SSHポート番号 例: 22>"; | ||
ssh_options_set( | ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, host.toUtf8().data()); | ||
ssh_options_set( | ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, user.toUtf8().data()); | ||
ssh_options_set( | ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT_STR, port.toUtf8().data()); | ||
// SSH接続 | // SSH接続 | ||
int rc = ssh_connect( | int rc = ssh_connect(my_ssh_session); | ||
if (rc != SSH_OK) { | if (rc != SSH_OK) { | ||
// 接続に失敗した場合 | // 接続に失敗した場合 | ||
fprintf(stderr, "Error connecting to host: %s\n", ssh_get_error( | fprintf(stderr, "Error connecting to host: %s\n", ssh_get_error(my_ssh_session)); | ||
ssh_free( | ssh_free(my_ssh_session); | ||
return -1; | return -1; | ||
| 226行目: | 241行目: | ||
// ~/.sshディレクトリ等にあるファイルに記述されているサーバのIDを検証 | // ~/.sshディレクトリ等にあるファイルに記述されているサーバのIDを検証 | ||
QString strErrMsg = ""; | QString strErrMsg = ""; | ||
if(VerifyKnownsHost( | if(VerifyKnownsHost(my_ssh_session, strErrMsg) < 0) | ||
{ | { | ||
fprintf(stderr, "%s\n", strErrMsg.toUtf8().constData(); | fprintf(stderr, "%s\n", strErrMsg.toUtf8().constData(); | ||
if( | if(my_ssh_session != nullptr) | ||
{ | { | ||
ssh_disconnect( | ssh_disconnect(my_ssh_session); | ||
ssh_free( | ssh_free(my_ssh_session); | ||
} | } | ||
| 243行目: | 258行目: | ||
// 秘密鍵のパスフレーズを設定していない場合 | // 秘密鍵のパスフレーズを設定していない場合 | ||
rc = ssh_userauth_privatekey_file( | rc = ssh_userauth_privatekey_file(my_ssh_session, nullptr, private_key_path, nullptr); | ||
// 秘密鍵のパスフレーズを設定している場合 | // 秘密鍵のパスフレーズを設定している場合 | ||
rc = ssh_userauth_privatekey_file( | rc = ssh_userauth_privatekey_file(my_ssh_session, nullptr, private_key_path, "<秘密鍵のパスフレーズ>"); | ||
if (rc != SSH_AUTH_SUCCESS) { | if (rc != SSH_AUTH_SUCCESS) { | ||
| 261行目: | 276行目: | ||
// SSH接続の切断 | // SSH接続の切断 | ||
ssh_disconnect( | ssh_disconnect(my_ssh_session); | ||
// SSHセッションの解放 | // SSHセッションの解放 | ||
ssh_free( | ssh_free(my_ssh_session); | ||
return 0; | return 0; | ||
} | } | ||
int VerifyKnownsHost(ssh_session | int VerifyKnownsHost(ssh_session my_ssh_session, QString &strErrMsg) | ||
{ | { | ||
// Authenticating the server. | // Authenticating the server. | ||
ssh_key srv_pubkey = {}; | ssh_key srv_pubkey = {}; | ||
if(ssh_get_server_publickey( | if(ssh_get_server_publickey(my_ssh_session, &srv_pubkey) < 0) | ||
{ | { | ||
strErrMsg = tr("Failed to get public key."); | strErrMsg = tr("Failed to get public key."); | ||
| 293行目: | 308行目: | ||
} | } | ||
auto state = ssh_session_is_known_server( | auto state = ssh_session_is_known_server(my_ssh_session); | ||
if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_OK) | if(state == ssh_known_hosts_e::SSH_KNOWN_HOSTS_OK) | ||
{ // Authentication Successful | { // Authentication Successful | ||
| 341行目: | 356行目: | ||
else | else | ||
{ | { | ||
iRet = ssh_session_update_known_hosts( | iRet = ssh_session_update_known_hosts(my_ssh_session); | ||
if(iRet < 0) | if(iRet < 0) | ||
{ | { | ||
| 368行目: | 383行目: | ||
else | else | ||
{ | { | ||
iRet = ssh_session_update_known_hosts( | iRet = ssh_session_update_known_hosts(my_ssh_session); | ||
if(iRet < 0) | if(iRet < 0) | ||
{ | { | ||
| 389行目: | 404行目: | ||
return 0; | return 0; | ||
} | } </syntaxhighlight> | ||
<br><br> | <br><br> | ||
| 403行目: | 417行目: | ||
<br><br> | <br><br> | ||
== | == libSSH2ライブラリを使用したコマンドの使用例 == | ||
==== ブロッキングモード ==== | |||
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br> | |||
<br> | |||
以下の例は、<u>ブロッキングモード</u>でlsコマンドを実行している。<br> | |||
<br> | |||
<syntaxhighlight lang="make"> | |||
# .pro プロジェクトファイル | |||
# QTcpSocketを使用する場合 | |||
QT += network | |||
# pkg-configを使用する場合 | |||
CONFIG += link_pkgconfig | |||
LIBS += \ | |||
-L/<libSSH2のインストールディレクトリ>/lib64 -lssh2 | |||
# pkg-configを使用しない場合 | |||
LIBS += \ | |||
-L/<libSSH2のインストールディレクトリ>/lib64 -lssh2 | |||
INCLUDEPATH += \ | |||
/<libSSH2のインストールディレクトリ>/include | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// main.cpp | |||
#include <QCoreApplication> | #include <QCoreApplication> | ||
#include < | #include <QTcpSocket> | ||
#include <QDebug> | #include <QDebug> | ||
#include <libssh2.h> | #include <libssh2.h> | ||
#include "DivideByZeroException.h" | #include "DivideByZeroException.h" | ||
void DisConnect(QTcpSocket &sock, LIBSSH2_SESSION *session); | |||
int ExecCommand(QTcpSocket &sock, LIBSSH2_SESSION *session); | |||
void DisConnect( | |||
int | |||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||
| 431行目: | 458行目: | ||
int rc = 0; | int rc = 0; | ||
QTcpSocket sock; | |||
LIBSSH2_SESSION *session = nullptr; | LIBSSH2_SESSION *session = nullptr; | ||
// libSSH2オブジェクトの初期化 | |||
auto rc = libssh2_init(0); | |||
if (rc != 0) { | |||
qDebug() << "libssh2 initialization failed"; | |||
DisConnect(sock, session); | |||
return -1; | |||
} | } | ||
// | // QTcpSocketクラスのインスタンスを生成して、リモートPCに接続 | ||
sock.connectToHost(<リモートPCのIPアドレスまたはホスト名>, <リモートPCにSSH接続するポート番号>); | |||
if ( | |||
qDebug() << | // 最大10[秒]待機 | ||
if (!sock.waitForConnected(10000)) { | |||
qDebug() << "SSH接続に失敗:" << socket.errorString(); | |||
DisConnect(sock, session); | DisConnect(sock, session); | ||
| 453行目: | 482行目: | ||
} | } | ||
// | // SSHのセッションの初期化 | ||
session = libssh2_session_init(); | |||
if ( | if (!session) { | ||
qDebug() << | qDebug() << "SSHのセッションの初期化に失敗"; | ||
DisConnect(sock, session); | DisConnect(sock, session); | ||
| 462行目: | 491行目: | ||
} | } | ||
// SSHのハンドシェイク | |||
if (libssh2_session_handshake(session, sock.socketDescriptor()) != 0) { | |||
qDebug() << "SSHのハンドシェイクに失敗"; | |||
// | |||
if ( | |||
qDebug() << | |||
DisConnect(sock, session); | DisConnect(sock, session); | ||
| 475行目: | 499行目: | ||
} | } | ||
// | // リモートPCのフィンガープリントを確認 | ||
session | auto fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); | ||
qDebug() << "リモートPCのフィンガープリント:" << fingerprint; | |||
// | // 認証方法の確認 | ||
auto userauth_list = libssh2_userauth_list(session, "<リモートPCのユーザ名>", strlen(USERNAME)); | |||
qDebug() << "認証方法:" << userauth_list; | |||
// | // パスワード認証を行う場合 | ||
if (libssh2_userauth_password(session, "< | //if (libssh2_userauth_password(session, "<リモートPCのユーザ名>", "<リモートPCのユーザパスワード>") != 0) { | ||
// qDebug() << "パスワードによる認証に失敗"; | |||
// return -1; | |||
//} | |||
// 公開鍵認証 | |||
if (libssh2_userauth_publickey_fromfile(session, "<リモートPCのユーザ名>", "<公開鍵ファイルのパス>", "<秘密鍵ファイルのパス>", "<秘密鍵のパスフレーズ>") != 0) { | |||
qDebug() << "公開鍵認証に失敗"; | |||
DisConnect(sock, session); | DisConnect(sock, session); | ||
| 492行目: | 524行目: | ||
// SSH接続後の処理 | // SSH接続後の処理 | ||
// | // リモートPC上でls -alコマンドを実行 | ||
rc = | rc = ExecCommand(sock, session); | ||
if (rc != 0) { | if (rc != 0) { | ||
DisConnect(sock, session); | DisConnect(sock, session); | ||
| 506行目: | 538行目: | ||
} | } | ||
void DisConnect( | void DisConnect(QTcpSocket &sock, LIBSSH2_SESSION *session) | ||
{ | { | ||
// セッションの終了 | // セッションの終了 | ||
| 516行目: | 548行目: | ||
// ソケットを閉じる | // ソケットを閉じる | ||
if (sock | if(sock.isOpen()) { | ||
sock.close(); | |||
} | } | ||
| 533行目: | 558行目: | ||
} | } | ||
int | int ExecCommand(QTcpSocket &sock, LIBSSH2_SESSION *session) | ||
{ | { | ||
// | // チャンネルをオープン | ||
LIBSSH2_CHANNEL *channel = | LIBSSH2_CHANNEL *channel = libssh2_channel_open_session(session); | ||
if (!channel) { | |||
qDebug() << "チャンネルのオープンに失敗"; | |||
return -1; | |||
} | |||
// リモートPC上でls -alコマンドを実行 | |||
if (libssh2_channel_exec(channel, "ls -la") != 0) { | |||
if( | qDebug() << "コマンドの実行に失敗"; | ||
qDebug() << | |||
return -1; | return -1; | ||
} | } | ||
// | // ls -alコマンドの実行結果を取得 | ||
// | int rc = 0; | ||
QByteArray buffer; | |||
//// | buffer.resize(1024); // バッファサイズを1024バイトに指定 | ||
do { | |||
//// | rc = libssh2_channel_read(channel, buffer.data(), buffer.size()); | ||
if (rc > 0) { | |||
if (! | qDebug().noquote() << QString::fromUtf8(buffer.constData(), rc); | ||
qDebug() << | } | ||
return | else if (rc < 0) { | ||
qDebug() << "Error reading channel:" << rc; | |||
break; | |||
} | |||
} while (rc > 0); | |||
// チャンネルの終了を確認 | |||
// 終了コードおよび終了シグナルを取得して表示 | |||
int exitcode = 127; | |||
char *exitsignal = nullptr; | |||
rc = libssh2_channel_close(channel); | |||
if (rc == 0) { | |||
exitcode = libssh2_channel_get_exit_status(channel); | |||
libssh2_channel_get_exit_signal(channel, &exitsignal, nullptr, nullptr, nullptr, nullptr, nullptr); | |||
} | |||
if (exitsignal) qDebug() << "Exit signal:" << exitsignal; | |||
else qDebug() << "Exit code:" << exitcode; | |||
return 0; | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// DivideByZeroException.h | |||
#ifndef DIVIDEBYZEROEXCEPTION_H | |||
#define DIVIDEBYZEROEXCEPTION_H | |||
#include <QException> | |||
class DivideByZeroException : public QException | |||
{ | |||
public: | |||
DivideByZeroException() {}; | |||
virtual ~DivideByZeroException() {}; | |||
const char* what() const noexcept override { | |||
return "Divide by zero exception"; | |||
} | |||
}; | |||
#endif // DIVIDEBYZEROEXCEPTION_H | |||
</syntaxhighlight> | |||
<br> | |||
==== ノンブロッキングモード ==== | |||
以下の例では、リモート側のPCにSSH接続して、lsコマンドを実行してその結果をローカル側のPCに表示している。<br> | |||
<br> | |||
以下の例は、<u>ノンブロッキングモード</u>でlsコマンドを実行している。<br> | |||
<u>ノンブロッキングモード</u> (シグナル / スロット) で設計する場合、libSSH2ライブラリの関数呼び出しは即座に返されて、処理がバックグラウンドで非同期に進行する。<br> | |||
これにより、プログラムは他の処理を続行でき、必要に応じてリモートホストとの通信が完了するのを待つことができる。<br> | |||
<br> | |||
ノンブロッキングモードを使用する場合、特に入出力操作が発生する待ち時間を最小限に抑え、プログラムがより効率的に動作することが期待される。<br> | |||
しかし、ノンブロッキングモードを扱う際には、非同期処理やイベント駆動型のプログラミングに慣れる必要がある。<br> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SSHClient.hファイル | |||
#include <QCoreApplication> | |||
#include <QTcpSocket> | |||
#include <QTimer> | |||
#include <QDebug> | |||
#include <libssh2.h> | |||
class SSHClient : public QObject | |||
{ | |||
Q_OBJECT | |||
private: | |||
QTcpSocket *m_Socket; | |||
LIBSSH2_SESSION *m_Session; | |||
LIBSSH2_CHANNEL *m_Channel; | |||
QString m_Host; | |||
quint16 m_Port; | |||
QString m_User; | |||
QString m_Passwaord; | |||
QString m_PubKey; | |||
QString m_PrivateKey; | |||
QString m_Passphrase; | |||
public: | |||
SSHClient(QString host, quint16 port, QString user, QString password, QObject *parent = nullptr); | |||
SSHClient(QString host, quint16 port, QString user, | |||
QString pubkey, QString privkey, QString phrase, QObject *parent = nullptr); | |||
~SSHClient(); | |||
void connectToHost(); | |||
private slots: | |||
void onConnected(); | |||
void authenticateUser(); | |||
void openChannel(); | |||
void executeCommand(); | |||
void onReadyRead(); | |||
void readOutput(); | |||
void closeChannel(); | |||
}; | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// SSHClient.cppファイル | |||
#include "SSHClient.h" | |||
SSHClient::SSHClient(QString host, quint16 port, QString user, QString password, QObject *parent = nullptr) : | |||
QObject(parent), m_Session(nullptr), m_Channel(nullptr), m_Host(host), m_Port(port), m_User(user), m_Password(password) | |||
{ | |||
m_Socket = new QTcpSocket(this); | |||
connect(m_Socket, &QTcpSocket::connected, this, &SSHClient::onConnected); | |||
connect(m_Socket, &QTcpSocket::readyRead, this, &SSHClient::onReadyRead); | |||
// libSSH2ライブラリの初期化 | |||
if (libssh2_init(0) != 0) { | |||
qDebug() << "libSSH2ライブラリの初期化に失敗"; | |||
return; | |||
} | |||
} | |||
SSHClient::SSHClient(QString host, quint16 port, QString user, QString pubkey, QString privkey, QString phrase, QObject *parent = nullptr) : | |||
QObject(parent), m_Session(nullptr), m_Channel(nullptr), | |||
m_Host(host), m_Port(port), m_User(user), m_PublicKey(pubkey), m_PrivateKey(privkey), m_Passphrase(phrase) | |||
{ | |||
m_Socket = new QTcpSocket(this); | |||
connect(m_Socket, &QTcpSocket::connected, this, &SSHClient::onConnected); | |||
connect(m_Socket, &QTcpSocket::readyRead, this, &SSHClient::onReadyRead); | |||
// libSSH2ライブラリの初期化 | |||
if (libssh2_init(0) != 0) { | |||
qDebug() << "libSSH2ライブラリの初期化に失敗"; | |||
return; | |||
} | |||
} | |||
SSHClient::~SSHClient() | |||
{ | |||
if (m_Channel) libssh2_channel_free(m_Channel); | |||
if (m_Session) { | |||
libssh2_session_disconnect(m_Session, "Normal Shutdown"); | |||
libssh2_session_free(m_Session); | |||
} | |||
libssh2_exit(); | |||
} | |||
void SSHClient::connectToHost() | |||
{ | |||
m_Socket->connectToHost(m_Host, m_Port); | |||
} | |||
void SSHClient::onConnected() | |||
{ | |||
qDebug() << "ホストへの接続に成功"; | |||
m_Session = libssh2_session_init(); | |||
libssh2_session_set_blocking(m_Session, 0); | |||
int rc = 0; | |||
do { | |||
rc = libssh2_session_handshake(m_Session, m_Socket->socketDescriptor()); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc) { | |||
qDebug() << "SSHのセッションの確立に失敗:" << rc; | |||
return; | |||
} | |||
authenticateUser(); | |||
} | |||
void SSHClient::authenticateUser() | |||
{ | |||
int rc = 0; | |||
do { | |||
// パスワード認証を行う場合 | |||
//rc = libssh2_userauth_password(m_Session, | |||
// m_User.toUtf8().constData(), | |||
// m_Password.toUtf8().constData()); | |||
// 公開鍵認証を行う場合 | |||
rc = libssh2_userauth_publickey_fromfile(m_Session, | |||
m_User.toUtf8().constData(), | |||
"", // クライアントPCに秘密鍵があり、 | |||
// リモートPC側に公開鍵が設置されている場合 | |||
m_PrivateKey.toUtf8().constData(), | |||
m_Passphrase.isEmpty() ? nullptr : m_Passphrase.toUtf8().constData()); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
if (rc) { | |||
qDebug() << "認証に失敗:" << rc; | |||
return; | |||
} | } | ||
openChannel(); | |||
} | |||
void SSHClient::openChannel() | |||
{ | |||
int rc = 0; | |||
do { | do { | ||
m_Channel = libssh2_channel_open_session(m_Session); | |||
} while (m_Channel == nullptr && libssh2_session_last_error(m_Session, nullptr, nullptr, 0) == LIBSSH2_ERROR_EAGAIN); | |||
if (!m_Channel) { | |||
qDebug() << "チャンネルのオープンに失敗"; | |||
return; | |||
} | |||
executeCommand(); | |||
} | |||
void SSHClient::executeCommand() | |||
{ | |||
int rc = 0; | |||
do { | |||
rc = libssh2_channel_exec(m_Channel, "ls -la"); | |||
} while (rc == LIBSSH2_ERROR_EAGAIN); | |||
return | if (rc) { | ||
qDebug() << "lsコマンドの実行に失敗:" << rc; | |||
return; | |||
} | |||
// lsコマンドの出力結果を取得を開始 | |||
QTimer::singleShot(0, this, &SSHClient::readOutput); | |||
} | |||
void SSHClient::onReadyRead() | |||
{ | |||
readOutput(); | |||
} | |||
void SSHClient::readOutput() | |||
{ | |||
if (!m_Channel) return; | |||
QByteArray buffer; | |||
buffer.resize(1024); | |||
int rc = 0; | |||
while (rc != LIBSSH2_ERROR_EAGAIN) { | |||
rc = libssh2_channel_read(m_Channel, buffer.data(), buffer.size()); | |||
if (rc > 0) { | |||
qDebug().noquote() << QString::fromUtf8(buffer.constData(), rc); | |||
} | |||
else if (rc < 0) { | |||
qDebug() << "チャンネルの読み取りエラー:" << rc; | |||
closeChannel(); | |||
return; | |||
} | } | ||
} | } | ||
// チャンネルがEOFかどうかを確認 | |||
if (libssh2_channel_eof(m_Channel) == 1) { | |||
closeChannel(); | |||
} | |||
else { | |||
// 続きを読み込む | |||
QTimer::singleShot(0, this, &SSHClient::readOutput); | |||
} | |||
} | |||
void SSHClient::closeChannel() | |||
{ | |||
if (!m_Channel) return; | |||
int | int rc = 0; | ||
do { | do { | ||
rc = libssh2_channel_close(m_Channel); | |||
if( | } while (rc == LIBSSH2_ERROR_EAGAIN); | ||
if (rc == 0) { | |||
int exitcode = libssh2_channel_get_exit_status(m_Channel); | |||
char *exitsignal = nullptr; | |||
libssh2_channel_get_exit_signal(m_Channel, &exitsignal, nullptr, nullptr, nullptr, nullptr, nullptr); | |||
if (exitsignal) { | |||
qDebug() << "Exit signal:" << exitsignal; | |||
} | |||
else { | |||
qDebug() << "Exit code:" << exitcode; | |||
} | } | ||
} | |||
libssh2_channel_free(m_Channel); | |||
m_Channel = nullptr; | |||
// Disconnect from the host | |||
m_Socket->disconnectFromHost(); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
// main.cppファイル | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
// パスワード認証を行う場合 | |||
//SSHClient client("<リモートPC側のIPアドレスまたはホスト名>", <リモートPCのポート番号>, | |||
// "<リモートPC側のユーザ名>", "<リモートPC側のユーザパスワード>"); | |||
// 公開鍵認証を行う場合 | |||
SSHClient client("<リモートPC側のIPアドレスまたはホスト名>", <リモートPCのポート番号>, | |||
"<リモートPC側のユーザ名>", | |||
"<公開鍵ファイルのパス>", // クライアントPCに秘密鍵があり、リモートPC側に公開鍵が設置されている場合は空欄 ("") にする | |||
"<秘密鍵ファイルのパス>", | |||
"<秘密鍵のパスフレーズ>"); | |||
client.connectToHost(); | |||
/ | return a.exec(); | ||
} | |||
</syntaxhighlight> | |||
<br><br> | |||
== SCPコマンドの使用例 == | |||
libSSHライブラリおよびlibSSH2ライブラリを使用したSCPコマンドの使用例は、以下に示すページに記載している。<br> | |||
* [[Qtの基礎_-_SCP#libSSHライブラリを使用したSCPコマンドの使用例|libSSHライブラリを使用したSCPコマンドの使用例]] | |||
* [[Qtの基礎_-_SCP#libSSH2ライブラリを使用したSCPコマンドの使用例|libSSH2ライブラリを使用したSCPコマンドの使用例]] | |||
<br><br> | |||
== sshdコマンドの使用 == | |||
==== OpenSSHのソースコードのダウンロード ==== | |||
[https://www.openssh.com/portable.html OpenSSHの公式Webサイト]にアクセスして、ソースコードをダウンロードする。<br> | |||
ダウンロードしたファイルを解凍する。<br> | |||
tar xf openssh-<バージョン>.tar.gz | |||
<br> | |||
このディレクトリ内に必要なヘッダファイル等が存在する。<br> | |||
<br> | |||
なお、OpenSSHのライセンスの全てのコンポーネントは、BSDライセンス、もしくはそれよりも自由なライセンスに属している。<br> | |||
<br> | |||
==== sshd -tコマンド ==== | |||
以下の例では、openSSHライブラリを使用して、<code>sshd -t</code>コマンドと同様、指定された設定ファイルの解析と妥当性を確認している。<br> | |||
<br> | |||
# <code>initialize_server_options</code>関数を呼び出して、サーバオプションを初期化する。 | |||
# コマンドライン引数からSSHの設定ファイルのパスを取得する。<br>引数が指定されていない場合は、デフォルトの"sshd_config"ファイルを使用する。 | |||
# <code>parse_server_config_depth</code>関数を呼び出して、指定されたSSHの設定ファイルを解析する。<br>解析に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。 | |||
# <code>validate_server_config</code>関数を呼び出して、解析された設定ファイルの妥当性を確認する。<br>確認に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。 | |||
# SSHの設定ファイルの解析と妥当性の結果に応じて、成功または失敗のメッセージを表示している。 | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QCoreApplication> | |||
#include <QDebug> | |||
#include <cstdio> | |||
#include <cstdlib> | |||
#include <cstring> | |||
#include <unistd.h> | |||
#include <sshbuf.h> | |||
#include <sshkey.h> | |||
#include <authfile.h> | |||
#include <auth-options.h> | |||
#include <servconf.h> | |||
int main(int argc, char *argv[]) | |||
{ | |||
QCoreApplication a(argc, argv); | |||
ServerOptions options; | |||
initialize_server_options(&options); | |||
// コマンドライン引数からSSHの設定ファイルのパスを取得 | |||
QString configFile = "sshd_config"; | |||
if (a.arguments().size() > 1) { | |||
configFile = a.arguments().at(1); | |||
} | } | ||
// SSHの設定ファイルの解析 | |||
qDebug() << QString(" | if (parse_server_config_depth(&options, configFile.toUtf8().constData(), NULL, 0) != 0) { | ||
qDebug() << QString("SSHの設定ファイルのパースに失敗: %1).arg(configFile); | |||
return -1; | |||
} | } | ||
// SSHの設定ファイルの妥当性を確認 | |||
if (validate_server_config(&options) != 0) { | |||
qDebug() << QString("SSHの設定ファイルに誤りがあります: %1").arg(configFile); | |||
return -1; | |||
} | |||
qDebug() << QString(" | qDebug() << QString("SSHの設定ファイル (%1) は正常です).arg(configFile); | ||
return 0; | return 0; | ||
} | } | ||
</syntaxhighlight> | |||
<br> | |||
==== sshd -Tコマンド ==== | |||
以下の例では、openSSHライブラリを使用して、<code>sshd -T</code>コマンドと同様、現在の設定オプションの値をダンプ形式で表示している。<br> | |||
<br> | |||
# <code>initialize_server_options</code>関数を呼び出して、サーバオプションを初期化する。 | |||
# <code>fill_default_server_options</code>関数を呼び出して、デフォルトのサーバオプションを設定する。 | |||
# <code>parse_server_config_depth</code>関数を呼び出して、sshd_configファイルを解析する。<br>解析に成功した場合は<code>0</code>、失敗した場合は<code>0以外</code>の値を返す。 | |||
# 解析に成功した場合は、<code>dump_config</code>関数を呼び出して、設定オプションのダンプを表示する。<br>これは、<code>sshd -T</code>コマンドと同様、現在の設定オプションの値を表示する。 | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
#include <QCoreApplication> | |||
#include <QDebug> | |||
#include <cstdio> | |||
#include <cstdlib> | |||
#include <cstring> | |||
#include <unistd.h> | |||
#include <sshbuf.h> | |||
#include <sshkey.h> | |||
#include <authfile.h> | |||
#include <auth-options.h> | |||
#include <servconf.h> | |||
int | int main(int argc, char *argv[]) | ||
{ | { | ||
QCoreApplication a(argc, argv); | |||
// SSHの設定ファイルオプション | |||
ServerOptions options; | |||
initialize_server_options(&options); | |||
fill_default_server_options(&options); | |||
if (parse_server_config_depth(&options, "sshd_config", NULL, 0) != 0) { | |||
qDebug() << "sshd_configファイルのパースに失敗"; | |||
if( | return -1; | ||
} | |||
qDebug() << "========= Dump of configuration options ========="; | |||
dump_config(&options); | |||
qDebug() << "================================================"; | |||
return | return 0; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> | ||
{{#seo: | |||
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki | |||
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 | |||
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux | |||
|image=/resources/assets/MochiuLogo_Single_Blue.png | |||
}} | |||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:Qt]] | [[カテゴリ:Qt]] | ||