1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-08-01 11:26:52 +03:00

examples: Reformat ssh_server.c

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
This commit is contained in:
Jakub Jelen
2024-07-15 12:37:20 +02:00
committed by Sahana Prasad
parent a001e19882
commit 17a8a8b3c3

View File

@ -135,52 +135,53 @@ static struct argp_option options[] = {
}; };
/* Parse a single option. */ /* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state) { static error_t
parse_opt(int key, char *arg, struct argp_state *state)
{
/* Get the input argument from argp_parse, which we /* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure. */ * know is a pointer to our arguments structure. */
ssh_bind sshbind = state->input; ssh_bind sshbind = state->input;
switch (key) { switch (key) {
case 'p': case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
break; break;
case 'k': case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break; break;
case 'r': case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break; break;
case 'e': case 'e':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break; break;
case 'a': case 'a':
strncpy(authorizedkeys, arg, DEF_STR_SIZE-1); strncpy(authorizedkeys, arg, DEF_STR_SIZE - 1);
break; break;
case 'u': case 'u':
strncpy(username, arg, sizeof(username) - 1); strncpy(username, arg, sizeof(username) - 1);
break; break;
case 'P': case 'P':
strncpy(password, arg, sizeof(password) - 1); strncpy(password, arg, sizeof(password) - 1);
break; break;
case 'v': case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
"3"); break;
break; case ARGP_KEY_ARG:
case ARGP_KEY_ARG: if (state->arg_num >= 1) {
if (state->arg_num >= 1) { /* Too many arguments. */
/* Too many arguments. */ argp_usage(state);
argp_usage (state); }
} ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg); break;
break; case ARGP_KEY_END:
case ARGP_KEY_END: if (state->arg_num < 1) {
if (state->arg_num < 1) { /* Not enough arguments. */
/* Not enough arguments. */ argp_usage(state);
argp_usage (state); }
} break;
break; default:
default: return ARGP_ERR_UNKNOWN;
return ARGP_ERR_UNKNOWN;
} }
return 0; return 0;
} }
@ -188,7 +189,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Our argp parser. */ /* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#else #else
static int parse_opt(int argc, char **argv, ssh_bind sshbind) { static int
parse_opt(int argc, char **argv, ssh_bind sshbind)
{
int no_default_keys = 0; int no_default_keys = 0;
int rsa_already_set = 0; int rsa_already_set = 0;
int ecdsa_already_set = 0; int ecdsa_already_set = 0;
@ -289,49 +292,74 @@ struct session_data_struct {
int authenticated; int authenticated;
}; };
static int data_function(ssh_session session, ssh_channel channel, void *data, static int
uint32_t len, int is_stderr, void *userdata) { data_function(ssh_session session,
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; ssh_channel channel,
void *data,
uint32_t len,
int is_stderr,
void *userdata)
{
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
(void) session; (void)session;
(void) channel; (void)channel;
(void) is_stderr; (void)is_stderr;
if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) { if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
return 0; return 0;
} }
return write(cdata->child_stdin, (char *) data, len); return write(cdata->child_stdin, (char *)data, len);
} }
static int pty_request(ssh_session session, ssh_channel channel, static int
const char *term, int cols, int rows, int py, int px, pty_request(ssh_session session,
void *userdata) { ssh_channel channel,
const char *term,
int cols,
int rows,
int py,
int px,
void *userdata)
{
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata; struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
int rc;
(void) session; (void)session;
(void) channel; (void)channel;
(void) term; (void)term;
cdata->winsize->ws_row = rows; cdata->winsize->ws_row = rows;
cdata->winsize->ws_col = cols; cdata->winsize->ws_col = cols;
cdata->winsize->ws_xpixel = px; cdata->winsize->ws_xpixel = px;
cdata->winsize->ws_ypixel = py; cdata->winsize->ws_ypixel = py;
if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL, rc = openpty(&cdata->pty_master,
cdata->winsize) != 0) { &cdata->pty_slave,
NULL,
NULL,
cdata->winsize);
if (rc != 0) {
fprintf(stderr, "Failed to open pty\n"); fprintf(stderr, "Failed to open pty\n");
return SSH_ERROR; return SSH_ERROR;
} }
return SSH_OK; return SSH_OK;
} }
static int pty_resize(ssh_session session, ssh_channel channel, int cols, static int
int rows, int py, int px, void *userdata) { pty_resize(ssh_session session,
ssh_channel channel,
int cols,
int rows,
int py,
int px,
void *userdata)
{
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata; struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
(void) session; (void)session;
(void) channel; (void)channel;
cdata->winsize->ws_row = rows; cdata->winsize->ws_row = rows;
cdata->winsize->ws_col = cols; cdata->winsize->ws_col = cols;
@ -345,30 +373,36 @@ static int pty_resize(ssh_session session, ssh_channel channel, int cols,
return SSH_ERROR; return SSH_ERROR;
} }
static int exec_pty(const char *mode, const char *command, static int
struct channel_data_struct *cdata) { exec_pty(const char *mode,
switch(cdata->pid = fork()) { const char *command,
case -1: struct channel_data_struct *cdata)
close(cdata->pty_master); {
close(cdata->pty_slave); cdata->pid = fork();
fprintf(stderr, "Failed to fork\n"); switch (cdata->pid) {
return SSH_ERROR; case -1:
case 0: close(cdata->pty_master);
close(cdata->pty_master); close(cdata->pty_slave);
if (login_tty(cdata->pty_slave) != 0) { fprintf(stderr, "Failed to fork\n");
exit(1); return SSH_ERROR;
} case 0:
execl("/bin/sh", "sh", mode, command, NULL); close(cdata->pty_master);
exit(0); if (login_tty(cdata->pty_slave) != 0) {
default: exit(1);
close(cdata->pty_slave); }
/* pty fd is bi-directional */ execl("/bin/sh", "sh", mode, command, NULL);
cdata->child_stdout = cdata->child_stdin = cdata->pty_master; exit(0);
default:
close(cdata->pty_slave);
/* pty fd is bi-directional */
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
} }
return SSH_OK; return SSH_OK;
} }
static int exec_nopty(const char *command, struct channel_data_struct *cdata) { static int
exec_nopty(const char *command, struct channel_data_struct *cdata)
{
int in[2], out[2], err[2]; int in[2], out[2], err[2];
/* Do the plumbing to be able to talk with the child process. */ /* Do the plumbing to be able to talk with the child process. */
@ -382,23 +416,24 @@ static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
goto stderr_failed; goto stderr_failed;
} }
switch(cdata->pid = fork()) { cdata->pid = fork();
case -1: switch (cdata->pid) {
goto fork_failed; case -1:
case 0: goto fork_failed;
/* Finish the plumbing in the child process. */ case 0:
close(in[1]); /* Finish the plumbing in the child process. */
close(out[0]); close(in[1]);
close(err[0]); close(out[0]);
dup2(in[0], STDIN_FILENO); close(err[0]);
dup2(out[1], STDOUT_FILENO); dup2(in[0], STDIN_FILENO);
dup2(err[1], STDERR_FILENO); dup2(out[1], STDOUT_FILENO);
close(in[0]); dup2(err[1], STDERR_FILENO);
close(out[1]); close(in[0]);
close(err[1]); close(out[1]);
/* exec the requested command. */ close(err[1]);
execl("/bin/sh", "sh", "-c", command, NULL); /* exec the requested command. */
exit(0); execl("/bin/sh", "sh", "-c", command, NULL);
exit(0);
} }
close(in[0]); close(in[0]);
@ -424,15 +459,18 @@ stdin_failed:
return SSH_ERROR; return SSH_ERROR;
} }
static int exec_request(ssh_session session, ssh_channel channel, static int
const char *command, void *userdata) { exec_request(ssh_session session,
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; ssh_channel channel,
const char *command,
void *userdata)
{
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
(void)session;
(void)channel;
(void) session; if (cdata->pid > 0) {
(void) channel;
if(cdata->pid > 0) {
return SSH_ERROR; return SSH_ERROR;
} }
@ -442,14 +480,15 @@ static int exec_request(ssh_session session, ssh_channel channel,
return exec_nopty(command, cdata); return exec_nopty(command, cdata);
} }
static int shell_request(ssh_session session, ssh_channel channel, static int
void *userdata) { shell_request(ssh_session session, ssh_channel channel, void *userdata)
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata; {
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
(void) session; (void)session;
(void) channel; (void)channel;
if(cdata->pid > 0) { if (cdata->pid > 0) {
return SSH_ERROR; return SSH_ERROR;
} }
@ -460,8 +499,12 @@ static int shell_request(ssh_session session, ssh_channel channel,
return SSH_OK; return SSH_OK;
} }
static int subsystem_request(ssh_session session, ssh_channel channel, static int
const char *subsystem, void *userdata) { subsystem_request(ssh_session session,
ssh_channel channel,
const char *subsystem,
void *userdata)
{
/* subsystem requests behave similarly to exec requests. */ /* subsystem requests behave similarly to exec requests. */
if (strcmp(subsystem, "sftp") == 0) { if (strcmp(subsystem, "sftp") == 0) {
return exec_request(session, channel, SFTP_SERVER_PATH, userdata); return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
@ -469,11 +512,15 @@ static int subsystem_request(ssh_session session, ssh_channel channel,
return SSH_ERROR; return SSH_ERROR;
} }
static int auth_password(ssh_session session, const char *user, static int
const char *pass, void *userdata) { auth_password(ssh_session session,
struct session_data_struct *sdata = (struct session_data_struct *) userdata; const char *user,
const char *pass,
void *userdata)
{
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
(void) session; (void)session;
if (strcmp(user, username) == 0 && strcmp(pass, password) == 0) { if (strcmp(user, username) == 0 && strcmp(pass, password) == 0) {
sdata->authenticated = 1; sdata->authenticated = 1;
@ -484,13 +531,14 @@ static int auth_password(ssh_session session, const char *user,
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
static int auth_publickey(ssh_session session, static int
const char *user, auth_publickey(ssh_session session,
struct ssh_key_struct *pubkey, const char *user,
char signature_state, struct ssh_key_struct *pubkey,
void *userdata) char signature_state,
void *userdata)
{ {
struct session_data_struct *sdata = (struct session_data_struct *) userdata; struct session_data_struct *sdata = (struct session_data_struct *)userdata;
ssh_key key = NULL; ssh_key key = NULL;
FILE *fp = NULL; FILE *fp = NULL;
char line[AUTH_KEYS_MAX_LINE_SIZE] = {0}; char line[AUTH_KEYS_MAX_LINE_SIZE] = {0};
@ -501,8 +549,8 @@ static int auth_publickey(ssh_session session,
int i; int i;
enum ssh_keytypes_e type; enum ssh_keytypes_e type;
(void) user; (void)user;
(void) session; (void)session;
if (signature_state == SSH_PUBLICKEY_STATE_NONE) { if (signature_state == SSH_PUBLICKEY_STATE_NONE) {
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
@ -598,17 +646,21 @@ static int auth_publickey(ssh_session session,
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
static ssh_channel channel_open(ssh_session session, void *userdata) { static ssh_channel
struct session_data_struct *sdata = (struct session_data_struct *) userdata; channel_open(ssh_session session, void *userdata)
{
struct session_data_struct *sdata = (struct session_data_struct *)userdata;
sdata->channel = ssh_channel_new(session); sdata->channel = ssh_channel_new(session);
return sdata->channel; return sdata->channel;
} }
static int process_stdout(socket_t fd, int revents, void *userdata) { static int
process_stdout(socket_t fd, int revents, void *userdata)
{
char buf[BUF_SIZE]; char buf[BUF_SIZE];
int n = -1; int n = -1;
ssh_channel channel = (ssh_channel) userdata; ssh_channel channel = (ssh_channel)userdata;
if (channel != NULL && (revents & POLLIN) != 0) { if (channel != NULL && (revents & POLLIN) != 0) {
n = read(fd, buf, BUF_SIZE); n = read(fd, buf, BUF_SIZE);
@ -620,10 +672,12 @@ static int process_stdout(socket_t fd, int revents, void *userdata) {
return n; return n;
} }
static int process_stderr(socket_t fd, int revents, void *userdata) { static int
process_stderr(socket_t fd, int revents, void *userdata)
{
char buf[BUF_SIZE]; char buf[BUF_SIZE];
int n = -1; int n = -1;
ssh_channel channel = (ssh_channel) userdata; ssh_channel channel = (ssh_channel)userdata;
if (channel != NULL && (revents & POLLIN) != 0) { if (channel != NULL && (revents & POLLIN) != 0) {
n = read(fd, buf, BUF_SIZE); n = read(fd, buf, BUF_SIZE);
@ -635,7 +689,9 @@ static int process_stderr(socket_t fd, int revents, void *userdata) {
return n; return n;
} }
static void handle_session(ssh_event event, ssh_session session) { static void
handle_session(ssh_event event, ssh_session session)
{
int n; int n;
int rc = 0; int rc = 0;
@ -748,8 +804,8 @@ static void handle_session(ssh_event event, ssh_session session) {
ssh_channel_close(sdata.channel); ssh_channel_close(sdata.channel);
} }
} }
} while(ssh_channel_is_open(sdata.channel) && } while (ssh_channel_is_open(sdata.channel) &&
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0)); (cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
close(cdata.pty_master); close(cdata.pty_master);
close(cdata.child_stdin); close(cdata.child_stdin);
@ -782,12 +838,14 @@ static void handle_session(ssh_event event, ssh_session session) {
#ifdef WITH_FORK #ifdef WITH_FORK
/* SIGCHLD handler for cleaning up dead children. */ /* SIGCHLD handler for cleaning up dead children. */
static void sigchld_handler(int signo) { static void sigchld_handler(int signo)
(void) signo; {
(void)signo;
while (waitpid(-1, NULL, WNOHANG) > 0); while (waitpid(-1, NULL, WNOHANG) > 0);
} }
#else #else
static void *session_thread(void *arg) { static void *session_thread(void *arg)
{
ssh_session session = arg; ssh_session session = arg;
ssh_event event; ssh_event event;
@ -806,9 +864,10 @@ static void *session_thread(void *arg) {
} }
#endif #endif
int main(int argc, char **argv) { int main(int argc, char **argv)
ssh_bind sshbind; {
ssh_session session; ssh_bind sshbind = NULL;
ssh_session session = NULL;
int rc; int rc;
#ifdef WITH_FORK #ifdef WITH_FORK
struct sigaction sa; struct sigaction sa;
@ -846,7 +905,8 @@ int main(int argc, char **argv) {
} }
#endif /* HAVE_ARGP_H */ #endif /* HAVE_ARGP_H */
if(ssh_bind_listen(sshbind) < 0) { rc = ssh_bind_listen(sshbind);
if (rc < 0) {
fprintf(stderr, "%s\n", ssh_get_error(sshbind)); fprintf(stderr, "%s\n", ssh_get_error(sshbind));
ssh_bind_free(sshbind); ssh_bind_free(sshbind);
ssh_finalize(); ssh_finalize();
@ -861,34 +921,36 @@ int main(int argc, char **argv) {
} }
/* Blocks until there is a new incoming connection. */ /* Blocks until there is a new incoming connection. */
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) { rc = ssh_bind_accept(sshbind, session);
if (rc != SSH_ERROR) {
#ifdef WITH_FORK #ifdef WITH_FORK
ssh_event event; ssh_event event;
switch(fork()) { pid_t pid = fork();
case 0: switch (pid) {
/* Remove the SIGCHLD handler inherited from parent. */ case 0:
sa.sa_handler = SIG_DFL; /* Remove the SIGCHLD handler inherited from parent. */
sigaction(SIGCHLD, &sa, NULL); sa.sa_handler = SIG_DFL;
/* Remove socket binding, which allows us to restart the sigaction(SIGCHLD, &sa, NULL);
* parent process, without terminating existing sessions. */ /* Remove socket binding, which allows us to restart the
ssh_bind_free(sshbind); * parent process, without terminating existing sessions. */
ssh_bind_free(sshbind);
event = ssh_event_new(); event = ssh_event_new();
if (event != NULL) { if (event != NULL) {
/* Blocks until the SSH session ends by either /* Blocks until the SSH session ends by either
* child process exiting, or client disconnecting. */ * child process exiting, or client disconnecting. */
handle_session(event, session); handle_session(event, session);
ssh_event_free(event); ssh_event_free(event);
} else { } else {
fprintf(stderr, "Could not create polling context\n"); fprintf(stderr, "Could not create polling context\n");
} }
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session); ssh_free(session);
exit(0); exit(0);
case -1: case -1:
fprintf(stderr, "Failed to fork\n"); fprintf(stderr, "Failed to fork\n");
} }
#else #else
pthread_t tid; pthread_t tid;