remote_libssh/main.c

433 lines
16 KiB
C
Raw Normal View History

2022-05-07 13:18:59 +08:00
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <ctype.h>
2022-05-07 13:18:59 +08:00
#define LIBSSH_STATIC 1
#include <libssh/libssh.h>
#define CBC 1
#define CTR 1
#define ECB 1
#include "aes.h"
2022-05-07 13:18:59 +08:00
#define BUFFER_SIZE 1024
int verify_knownhost(ssh_session session)
{
enum ssh_known_hosts_e state;
unsigned char *hash = NULL;
ssh_key srv_pubkey = NULL;
size_t hlen;
char *hexa;
int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey);
if (rc < 0) {
return -1;
}
rc = ssh_get_publickey_hash(srv_pubkey, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
state = ssh_session_is_known_server(session);
switch (state) {
case SSH_KNOWN_HOSTS_OK:
/* OK */
break;
case SSH_KNOWN_HOSTS_CHANGED:
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_OTHER:
fprintf(stderr, "The host key for this server was not found but an other" "type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to" "confuse your client into thinking the key does not exist\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be" "automatically created.\n");
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
case SSH_KNOWN_HOSTS_UNKNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr, "The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
ssh_clean_pubkey_hash(&hash);
rc = ssh_session_update_known_hosts(session);
if (rc < 0) {
fprintf(stderr, "Error %s\n", strerror(errno));
return -1;
}
break;
case SSH_KNOWN_HOSTS_ERROR:
fprintf(stderr, "Error %s", ssh_get_error(session));
ssh_clean_pubkey_hash(&hash);
return -1;
}
ssh_clean_pubkey_hash(&hash);
return 0;
}
2022-05-14 16:27:28 +08:00
// 交互式外壳会话
int interactive_shell_session(ssh_session session, ssh_channel channel)
2022-05-07 13:18:59 +08:00
{
int rc;
2022-05-14 16:27:28 +08:00
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK)
return rc;
2022-05-07 13:18:59 +08:00
2022-05-14 16:27:28 +08:00
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK)
2022-05-07 13:18:59 +08:00
return rc;
2022-05-14 16:27:28 +08:00
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK)
return rc;
char buffer[256];
int nbytes, nwritten;
while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
struct timeval timeout;
ssh_channel in_channels[2], out_channels[2];
fd_set fds;
int maxfd;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
in_channels[0] = channel;
in_channels[1] = NULL;
FD_ZERO(&fds);
FD_SET(0, &fds);
FD_SET(ssh_get_fd(session), &fds);
maxfd = ssh_get_fd(session) + 1;
ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
if (out_channels[0] != NULL) {
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
return SSH_ERROR;
if (nbytes > 0) {
nwritten = write(1, buffer, nbytes);
if (nwritten != nbytes)
return SSH_ERROR;
}
}
if (FD_ISSET(0, &fds)) {
nbytes = read(0, buffer, sizeof(buffer));
if (nbytes < 0)
return SSH_ERROR;
if (nbytes > 0) {
nwritten = ssh_channel_write(channel, buffer, nbytes);
if (nbytes != nwritten)
return SSH_ERROR;
}
}
2022-05-07 13:18:59 +08:00
}
2022-05-14 16:27:28 +08:00
return rc;
}
// 执行远程命令
int execute_remote_command(ssh_channel channel, char *command)
{
int rc;
char buffer[256];
int nbytes;
2022-05-07 13:18:59 +08:00
rc = ssh_channel_request_exec(channel, command);
if (rc != SSH_OK) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) {
if (write(1, buffer, nbytes) != (unsigned int)nbytes) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0) {
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
2022-05-14 16:27:28 +08:00
return rc;
}
int show_remote_processes(ssh_session session, char *command, int is)
{
int rc;
ssh_channel channel;
// 分配一个新的信道
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
// 分配好的信道
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK) {
ssh_channel_free(channel);
return rc;
}
if (is) {
2022-05-14 16:27:28 +08:00
interactive_shell_session(session, channel);
} else {
2022-05-14 16:27:28 +08:00
execute_remote_command(channel, command);
}
2022-05-07 13:18:59 +08:00
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
int authenticate_pubkey(ssh_session session, char *priv_name, char *passphrase)
{
int rc;
ssh_key pkey = NULL;
//从文件中个导入密钥
rc = ssh_pki_import_privkey_file(priv_name, passphrase, NULL, NULL, &pkey);
if (rc != SSH_OK) {
exit(-1);
}
ssh_userauth_publickey(session, NULL, pkey);
ssh_key_free(pkey);
return rc;
}
static int oneHexChar2Hex(char hex)
{
int outHex = 0;
if (isdigit(hex)) {
outHex = hex - '0';
} else if (isupper(hex)) {
outHex = hex - 'A' + 10;
} else {
outHex = hex - 'a' + 10;
}
return outHex;
}
static int HexString2Hex(char *inHexString, char *outHex, int count)
2022-05-07 13:18:59 +08:00
{
int ret = -1;
int len = 0;
int i;
char ch1, ch2;
2022-05-14 16:27:28 +08:00
if (NULL == inHexString)
return -1;
2022-05-07 13:18:59 +08:00
len = count;
2022-05-07 13:18:59 +08:00
if (len < 1)
return -1;
2022-05-14 16:27:28 +08:00
len &= ~1;
for (i = 0; i < len; i += 2) {
ch1 = inHexString[i];
ch2 = inHexString[i + 1];
outHex[i / 2 + 1] = 0;
if (isxdigit(ch1) && isxdigit(ch2)) {
ch1 = oneHexChar2Hex(ch1);
ch2 = oneHexChar2Hex(ch2);
outHex[i / 2] = (ch1 << 4) | ch2;
} else {
goto EXIT;
}
2022-05-09 10:00:07 +08:00
}
return 0;
EXIT:
return ret;
}
static int rsa_file()
{
static uint8_t key[16] = "aixiao";
struct AES_ctx ctx;
AES_init_ctx(&ctx, key);
static char temp[] =
"6681E82581AF0A621B2D5A82C161F7D053482050524956415445204B45592D2D2D2D2D0A6233426C626E4E7A614331725A586B74646A454141414141436D466C637A49314E69316A6448494141414147596D4E796558423041414141474141414142446C4664306F54620A71634F3837615369703756582B55414141414541414141414541414147584141414142334E7A614331796332454141414144415141424141414267514463596A734B346330770A757649304B4163454A385132717975592B57545149456B53446A672B5A67614A484B444166765678706C35313368535151654D7253754558725372526277504C6148417051490A7A79715273506F6C64553630454B4B335058374A483269544C5A70715A4F396645323965686B4F332B45675836714456553854755871377558356D326F75374B6F37385641440A42527A53743772647A4D6A304A762B4D61414C664C736F464A4E4462753457633171772B5A486E3566385253752F65423548664878545955764F33614A39717855626332496A0A5035466E43336B4C49487638467A375A30514D394935622F6D754631375156394379754D67756E517841546A4F6D4252736A46717036796E7374756F53526846524B302B67530A453234734D4A58392B6C684237714B6F44746E306B54474B545369646B7539696171585436306E52377445455A556B726A34453469304541305633736E326E7745447371796E0A76635563736F5868615159726A31532F4345487A6242525A6F51724532444C4450676D702B55714F315679754D72483153497568705633754345616444776265474E755978610A306478797A457446306B44774252654B3254467073312F746F776D2B754D5A4B444C7658586A375775702F394E4233447376544A365575343969717431746E73524C39354F4D0A72653630352F5331653575587341414157417377326A4E747645773975746C336741744F6A516D68596E6F684B4C765732695A5162625379564446556A6F2F39324E733735710A6D623971317933714661447270496E36596A39386E44516239346B2B4A624F6848422B6148554F5A6739683572392F5439422F672F72624F574A436336634A762F2B4A6656460A6345324B504F7A634E70392B334A5A4635654742706E49365A7470305A4B7364684545422B6D754C514E6B757A44426D48386F50536D57642F4F39586355325276596B45342F0A70537349744835475975747861414B444D543063692B6342745252615742626859676657416A50727439467A313063676E58327669674B73754E6C4F34696B7875514C6B49630A6C776D73414B2F36656774466C68654258747A6C657037787059744174516A317652594846644A2B5842325439532F616672636F626B306B70755552737361317350464274770A5979453459644B77557154484F4C4B6E45374A686D65306558715759336A7A6A5A6D775651757131354F6679666470482F737265566A656F644478616B584E74484C556770420A5647456147446F69494F70624F59382F6A34746C7862673164672F32503932663265744758634675434476586273507A30727054327054315230544F746B644D3132375059520A504542333155465172434545614A7A4E4434704B342F41797579707A4A652F486F596B4B784A5659546534654A6A4959746B53713777656137455A68724B2F4E7447617346350A4253566A4655766F774C33564D563633312F59586778757935584A4A3857504A684A7632375A64682F54514E426E6E78664369477764564D626A4A6E706251636F742F6F66730A70453833696451472B546273373064756F396A2F774C7162625050366453436C6A6E61304E77626132355659543152783968576531794955426F48463736344568763342786E0A6C353453764D63425A644C4C634F57504B464F3076544C6B394E41496969762F4C79506B3854625836507676477A52523447307245646365686E387352366B335A7530454F4E0A582B334451344A6F7968577477446C583878666A5732592F6B313546583871737534395431344B484A7A56736D4B6E622B714C514F4F305858464A5166376F4D427652464E4F0A325743484370445A4C394D31725966336D337245455335447879332F4D6553685353536E45634D5962572B32364842364570324E41714D71703351464A2F45506D54485054710A446A62652F496B48642B376D72326E4B5842456B2F47736C6371384B5963613565704C446A616E367939496538434D55534843637038526F446E78326258642B344E534977560A7047616F34784747644C2B53567953734453545776754D47715152545464334253315869794D6A3174566C782B6B4B674449724D51655971764D646573306F6E3451795062570A7A4A4B3639462F454B36633654442F4D5567777652656C6D6F2F586D6250694A6D376749643673432F5149674877774F334173533245593056786E6D58444B4C7877324B72730A3630663079786A2B344B7679552B79316C774F5257445542564C657A4E313062692F37395A7A2B366F2B523137735A7448307A34633371753238552F6C3179554E6D386A4F750A33492B6F7269785830464551574E34634B32543856785446304A5A78472B2B4F412B763438736E563268636638786F7652764B45422F764A6F464559617851684B56527538740A4779745A6D473079534F3461686D3968764D653162322B6A4454597A363034545234424C54422B35774A4F2B7A722B3362356134596C7653536E6D4448695831634E786E4A4A0A622F42716D55714F417A614A4D564C4C747553
uint8_t Hex_string[sizeof(temp) / 2];
bzero(Hex_string, 0);
HexString2Hex((char *)temp, (char *)Hex_string, sizeof(temp));
2022-05-14 16:27:28 +08:00
AES_ECB_decrypt(&ctx, Hex_string);
//printf("%s\n", Hex_string);
2022-05-07 13:18:59 +08:00
FILE *fp = fopen("aixiao.rsa", "w");
if (fp == NULL) {
perror("fopen");
return -1;
}
fwrite(Hex_string, sizeof(Hex_string), 1, fp);
fclose(fp);
2022-05-07 13:18:59 +08:00
return 0;
}
static void help_information() {
2022-05-07 13:18:59 +08:00
puts("\n"
"remote command\n"
"Author: aixiao@aixiao.me\n"
"Usage: [-?hlfpkib]\n"
"\n"
" Options:\n"
2022-05-09 10:00:07 +08:00
" -l : host name\n"
2022-05-14 16:27:28 +08:00
" -p : host port\n"
2022-05-09 10:00:07 +08:00
" -u : user name(default: root)\n"
2022-05-14 16:27:28 +08:00
" -e : user passwd\n"
2022-05-07 13:18:59 +08:00
" -k : private key passwd\n"
2022-05-14 16:27:28 +08:00
" -f : private key file\n"
" -i : interactive shell session\n"
" -c : command\n"
2022-05-07 13:18:59 +08:00
" -? -h : help information\n");
exit(0);
}
int main(int argc, char *argv[], char **env)
{
int rc;
int is = 0;
2022-05-07 13:18:59 +08:00
int verbosity = SSH_LOG_PROTOCOL;
ssh_session my_ssh_session;
char host_ip[BUFFER_SIZE];
char password[BUFFER_SIZE];
2022-05-09 10:00:07 +08:00
char user[BUFFER_SIZE];
char *priv_name = "aixiao.rsa"; // 私钥文件名称
char priv_passwd[BUFFER_SIZE]; // 私钥的解密密钥
2022-05-07 13:18:59 +08:00
char command[BUFFER_SIZE];
int host_port = 22;
memset(host_ip, 0, BUFFER_SIZE);
memset(password, 0, BUFFER_SIZE);
2022-05-09 10:00:07 +08:00
memset(user, 0, BUFFER_SIZE);
2022-05-07 13:18:59 +08:00
memset(priv_passwd, 0, BUFFER_SIZE);
memset(command, 0, BUFFER_SIZE);
2022-05-14 16:27:28 +08:00
memcpy(user, "root", 4);
2022-05-07 13:18:59 +08:00
int opt;
2022-05-14 16:27:28 +08:00
char optstrs[] = "-:l:p:u:e:k:f:ic:h?";
2022-05-07 13:18:59 +08:00
while (-1 != (opt = getopt(argc, argv, optstrs))) {
switch (opt) {
case 'l':
strcpy(host_ip, optarg);
break;
2022-05-14 16:27:28 +08:00
case 'p':
2022-05-07 13:18:59 +08:00
host_port = atoi(optarg);
break;
2022-05-09 10:00:07 +08:00
case 'u':
strcpy(user, optarg);
break;
2022-05-14 16:27:28 +08:00
case 'e':
2022-05-07 13:18:59 +08:00
strcpy(password, optarg);
break;
case 'k':
memset(password, 0, BUFFER_SIZE);
strcpy(priv_passwd, optarg);
rsa_file();
break;
2022-05-14 16:27:28 +08:00
case 'f':
2022-05-07 13:18:59 +08:00
priv_name = optarg;
break;
2022-05-14 16:27:28 +08:00
case 'i':
is = 1;
break;
case 'c':
2022-05-07 13:18:59 +08:00
strcpy(command, optarg);
break;
case ':':
printf("\nMissing argument after: -%c\n", optopt);
2022-05-09 10:00:07 +08:00
exit(0);
2022-05-07 13:18:59 +08:00
case 'h':
case '?':
help_information();
default:
help_information();
}
}
my_ssh_session = ssh_new();
if (my_ssh_session == NULL) {
2022-05-07 13:18:59 +08:00
exit(-1);
}
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, host_ip);
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &host_port);
rc = ssh_connect(my_ssh_session);
// Verify the server's identity
if (verify_knownhost(my_ssh_session) < 0) {
2022-05-07 13:18:59 +08:00
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
if (strlen(password) > 1) {
2022-05-07 13:18:59 +08:00
// Authenticate ourselves
2022-05-09 10:00:07 +08:00
rc = ssh_userauth_password(my_ssh_session, user, password);
2022-05-07 13:18:59 +08:00
if (rc != SSH_AUTH_SUCCESS) {
fprintf(stderr, "Error authenticating with password: %s\n", ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
} else {
2022-05-07 13:18:59 +08:00
// 私钥认证
authenticate_pubkey(my_ssh_session, priv_name, priv_passwd);
}
// 传递远程命令
2022-05-14 16:27:28 +08:00
show_remote_processes(my_ssh_session, command, is);
2022-05-07 13:18:59 +08:00
// 从一个会话断开连接(服务器或客户端)
ssh_disconnect(my_ssh_session);
// 释放已分配的SSH会话句柄
ssh_free(my_ssh_session);
2022-05-14 16:27:28 +08:00
remove("aixiao.rsa");
2022-05-07 13:18:59 +08:00
return 0;
}