Loading...
Searching...
No Matches
ssh.c File Reference
`#include "arc/networking/ssh.h"`
`#include "arc/std/errno.h"`
`#include "arc/std/string.h"`
`#include <stdint.h>`
`#include <stdlib.h>`
`#include <libssh/libssh.h>`

Go to the source code of this file.

## Data Structures

struct | ARC_Ssh

## Functions

int | verify_knownhost (ssh_session session)
void | ARC_Ssh_Create (ARC_Ssh **ssh, char *host, char *user, char *password)
| creates ARC_Ssh type
void | ARC_Ssh_Destroy (ARC_Ssh *ssh)
| destroyes ARC_Ssh type
void | ARC_Ssh_RunInSession (ARC_Ssh *ssh, ARC_Ssh_SessionFn sessionFn)
| runs a callback function within a ssh session
void | ARC_Ssh_ExecStrInNewSession (ARC_Ssh *ssh, char *command)
ARC_String * | ARC_Ssh_ExecStrInNewSessionAndGetResponse (ARC_Ssh *ssh, char *command)

## Function Documentation

## ARC_Ssh_Create()

void ARC_Ssh_Create | ( | ARC_Ssh ** | ssh,
|  | char * | host,
|  | char * | user,
|  | char * | password )

creates ARC_Ssh type

Parameters

  ssh | ARC_Ssh to create

Definition at line 94 of file ssh.c.

{
*ssh = (ARC_Ssh *)malloc(sizeof(ARC_Ssh));
(*ssh)->session = ssh_new();
if((*ssh)->session == NULL){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_ERR("ARC_Ssh_Create(ssh), ssh session could not be created\n");
free(*ssh);
*ssh = NULL;
return;
}
if(host != NULL){
ssh_options_set((*ssh)->session, SSH_OPTIONS_HOST, host);
}
if(user != NULL){
ssh_options_set((*ssh)->session, SSH_OPTIONS_USER, user);
}
int32_t returnCode = ssh_connect((*ssh)->session);
if(returnCode != SSH_OK){
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_Create(ssh), ssh failed to connect to localhost: %s\n", ssh_get_error((*ssh)->session));
ssh_free((*ssh)->session);
free(*ssh);
*ssh = NULL;
return;
}
if(verify_knownhost((*ssh)->session) < 0){
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_ERR("ARC_Ssh_Create(ssh), ssh failed to verify knownhost\n");
ssh_disconnect((*ssh)->session);
ssh_free((*ssh)->session);
free(*ssh);
*ssh = NULL;
}
//if no password is provided try to connect with a public key
if(password == NULL){
returnCode = ssh_userauth_publickey_auto((*ssh)->session, NULL, NULL);
if(returnCode != SSH_AUTH_SUCCESS){
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_Create(ssh), ssh failed to authenticate with password: %s\n", ssh_get_error((*ssh)->session));
ssh_disconnect((*ssh)->session);
ssh_free((*ssh)->session);
free(*ssh);
*ssh = NULL;
}
ssh_send_ignore((*ssh)->session, "mpv https://youtu.be/1P5BSm_oFJg --input-ipc-server=/tmp/mpvsocket --no-terminal & disown");
return;
}
//try connecting with password
returnCode = ssh_userauth_password((*ssh)->session, NULL, password);
if(returnCode != SSH_AUTH_SUCCESS){
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_Create(ssh), ssh failed to authenticate with password: %s\n", ssh_get_error((*ssh)->session));
ssh_disconnect((*ssh)->session);
ssh_free((*ssh)->session);
free(*ssh);
*ssh = NULL;
}
}
ARC_ERRNO_CONNECTION
#define ARC_ERRNO_CONNECTION
Definition errno.h:12
arc_errno
int32_t arc_errno
Definition errno.c:5
ARC_ERRNO_NULL
#define ARC_ERRNO_NULL
Definition errno.h:6
verify_knownhost
int verify_knownhost(ssh_session session)
Definition ssh.c:15
ARC_Ssh
Definition ssh.c:11
ARC_Ssh::session
ssh_session session
Definition ssh.c:12

References arc_errno, ARC_ERRNO_CONNECTION, ARC_ERRNO_NULL, ARC_Ssh::session, and verify_knownhost().

## ARC_Ssh_Destroy()

void ARC_Ssh_Destroy | ( | ARC_Ssh * | ssh | ) |

destroyes ARC_Ssh type

Parameters

  ssh | ARC_Ssh to destroy

Definition at line 162 of file ssh.c.

{
if(ssh == NULL){
return;
}
ssh_disconnect(ssh->session);
ssh_free(ssh->session);
free(ssh);
}

References ARC_Ssh::session.

## ARC_Ssh_ExecStrInNewSession()

void ARC_Ssh_ExecStrInNewSession | ( | ARC_Ssh * | ssh,
|  | char * | command )

Definition at line 199 of file ssh.c.

{
ssh_channel channel;
channel = ssh_channel_new(ssh->session);
if(channel == NULL){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_ERR("ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to create channel\n");
return;
}
int32_t returnCode = ssh_channel_open_session(channel);
if(returnCode != SSH_OK){
ssh_channel_free(channel);
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to open session with return code: %d\n", returnCode);
return;
}
returnCode = ssh_channel_request_exec(channel, command);
if(returnCode != SSH_OK){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed when executing command with error code: %d\n", returnCode);
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
}
ARC_ERRNO_DATA
#define ARC_ERRNO_DATA
Definition errno.h:7

References arc_errno, ARC_ERRNO_CONNECTION, ARC_ERRNO_DATA, ARC_ERRNO_NULL, and ARC_Ssh::session.

## ARC_Ssh_ExecStrInNewSessionAndGetResponse()

ARC_String * ARC_Ssh_ExecStrInNewSessionAndGetResponse | ( | ARC_Ssh * | ssh,
|  | char * | command )

Definition at line 227 of file ssh.c.

{
ssh_channel channel;
channel = ssh_channel_new(ssh->session);
if(channel == NULL){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_ERR("ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to create channel\n");
return NULL;
}
int32_t returnCode = ssh_channel_open_session(channel);
if(returnCode != SSH_OK){
ssh_channel_free(channel);
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to open session with return code: %d\n", returnCode);
return NULL;
}
returnCode = ssh_channel_request_exec(channel, command);
if(returnCode != SSH_OK){
ssh_channel_close(channel);
ssh_channel_free(channel);
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed when executing command with error code: %d\n", returnCode);
return NULL;
}
//this is taken from https://api.libssh.org/master/libssh_tutor_command.html
char buffer[256];
int32_t bytesSize;
ARC_String *returnString = NULL;
bytesSize = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while(bytesSize > 0){
if(returnString == NULL){
ARC_String_Create(&returnString, buffer, bytesSize);
bytesSize = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
continue;
}
ARC_String_AppendCString(&returnString, (const char *)buffer, bytesSize);
bytesSize = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if(bytesSize < 0){
ssh_channel_close(channel);
ssh_channel_free(channel);
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_ERR("ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed when reading bytes from channel\n");
if(returnString != NULL){
ARC_String_Destroy(returnString);
}
return NULL;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return returnString;
}
ARC_String_AppendCString
void ARC_String_AppendCString(ARC_String **string, const char *cstring, uint64_t length)
appends to an ARC_String with an ARC_String
Definition string.c:130
ARC_String_Create
void ARC_String_Create(ARC_String **string, char *data, uint64_t length)
creates ARC_String type
Definition string.c:9
ARC_String_Destroy
void ARC_String_Destroy(ARC_String *string)
destroys ARC_String type
Definition string.c:52
ARC_String
substring position within a string
Definition string.h:14

References arc_errno, ARC_ERRNO_CONNECTION, ARC_ERRNO_DATA, ARC_ERRNO_NULL, ARC_String_AppendCString(), ARC_String_Create(), ARC_String_Destroy(), and ARC_Ssh::session.

## ARC_Ssh_RunInSession()

void ARC_Ssh_RunInSession | ( | ARC_Ssh * | ssh,
|  | ARC_Ssh_SessionFn | sessionFn )

runs a callback function within a ssh session

Parameters

  ssh | ARC_Ssh to create and run function in ssh session
  sessionFN | callback to run in a ssh session

Definition at line 172 of file ssh.c.

{
ssh_channel channel;
channel = ssh_channel_new(ssh->session);
if(channel == NULL){
arc_errno = ARC_ERRNO_NULL;
ARC_DEBUG_ERR("ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to create channel\n");
return;
}
int32_t returnCode = ssh_channel_open_session(channel);
if(returnCode != SSH_OK){
ssh_channel_free(channel);
arc_errno = ARC_ERRNO_CONNECTION;
ARC_DEBUG_LOG(arc_errno, "ARC_Ssh_RunInSession(ssh, sessionFn), ssh failed to open session with return code: %d\n", returnCode);
return;
}
// sessionFn(ssh, );
returnCode = ssh_channel_request_exec(channel, "export DISPLAY=:0 ; volume --inc");
printf("return code: %d\n", returnCode);
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
}

References arc_errno, ARC_ERRNO_CONNECTION, ARC_ERRNO_NULL, and ARC_Ssh::session.

## verify_knownhost()

int verify_knownhost | ( | ssh_session | session | ) |

Definition at line 15 of file ssh.c.

{
enum ssh_known_hosts_e state;
unsigned char *hash = NULL;
ssh_key srv_pubkey = NULL;
size_t hlen;
char buf[10];
char *hexa;
char *p;
int cmp;
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_hexa("Public key hash", 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);
p = fgets(buf, sizeof(buf), stdin);
if(p == NULL){
return -1;
}
cmp = strncasecmp(buf, "yes", 3);
if(cmp != 0){
return -1;
}
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;
}

Referenced by ARC_Ssh_Create().