Blame examples/samplesshd-cb.c

Packit Service 31306d
/* This is a sample implementation of a libssh based SSH server */
Packit Service 31306d
/*
Packit Service 31306d
Copyright 2003-2009 Aris Adamantiadis
Packit Service 31306d
Packit Service 31306d
This file is part of the SSH Library
Packit Service 31306d
Packit Service 31306d
You are free to copy this file, modify it in any way, consider it being public
Packit Service 31306d
domain. This does not apply to the rest of the library though, but it is
Packit Service 31306d
allowed to cut-and-paste working code from this file to any license of
Packit Service 31306d
program.
Packit Service 31306d
The goal is to show the API in action. It's not a reference on how terminal
Packit Service 31306d
clients must be made or how a client should react.
Packit Service 31306d
*/
Packit Service 31306d
Packit Service 31306d
#include "config.h"
Packit Service 31306d
Packit Service 31306d
#include <libssh/libssh.h>
Packit Service 31306d
#include <libssh/server.h>
Packit Service 31306d
#include <libssh/callbacks.h>
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_ARGP_H
Packit Service 31306d
#include <argp.h>
Packit Service 31306d
#endif
Packit Service 31306d
#include <stdlib.h>
Packit Service 31306d
#include <string.h>
Packit Service 31306d
#include <stdio.h>
Packit Service 31306d
Packit Service 31306d
#ifndef KEYS_FOLDER
Packit Service 31306d
#ifdef _WIN32
Packit Service 31306d
#define KEYS_FOLDER
Packit Service 31306d
#else
Packit Service 31306d
#define KEYS_FOLDER "/etc/ssh/"
Packit Service 31306d
#endif
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
#define USER "myuser"
Packit Service 31306d
#define PASSWORD "mypassword"
Packit Service 31306d
Packit Service 31306d
static int authenticated=0;
Packit Service 31306d
static int tries = 0;
Packit Service 31306d
static int error = 0;
Packit Service 31306d
static ssh_channel chan=NULL;
Packit Service 31306d
Packit Service 31306d
static int auth_password(ssh_session session, const char *user,
Packit Service 31306d
        const char *password, void *userdata){
Packit Service 31306d
    (void)userdata;
Packit Service 31306d
    printf("Authenticating user %s pwd %s\n",user, password);
Packit Service 31306d
    if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
Packit Service 31306d
        authenticated = 1;
Packit Service 31306d
        printf("Authenticated\n");
Packit Service 31306d
        return SSH_AUTH_SUCCESS;
Packit Service 31306d
    }
Packit Service 31306d
    if (tries >= 3){
Packit Service 31306d
        printf("Too many authentication tries\n");
Packit Service 31306d
        ssh_disconnect(session);
Packit Service 31306d
        error = 1;
Packit Service 31306d
        return SSH_AUTH_DENIED;
Packit Service 31306d
    }
Packit Service 31306d
    tries++;
Packit Service 31306d
    return SSH_AUTH_DENIED;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
Packit Service 31306d
    ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
Packit Service 31306d
    (void)userdata;
Packit Service 31306d
    printf("Authenticating user %s with gssapi principal %s\n",user, principal);
Packit Service 31306d
    if (creds != NULL)
Packit Service 31306d
        printf("Received some gssapi credentials\n");
Packit Service 31306d
    else
Packit Service 31306d
        printf("Not received any forwardable creds\n");
Packit Service 31306d
    printf("authenticated\n");
Packit Service 31306d
    authenticated = 1;
Packit Service 31306d
    return SSH_AUTH_SUCCESS;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
Packit Service 31306d
        int x,int y, int px, int py, void *userdata){
Packit Service 31306d
    (void) session;
Packit Service 31306d
    (void) channel;
Packit Service 31306d
    (void) term;
Packit Service 31306d
    (void) x;
Packit Service 31306d
    (void) y;
Packit Service 31306d
    (void) px;
Packit Service 31306d
    (void) py;
Packit Service 31306d
    (void) userdata;
Packit Service 31306d
    printf("Allocated terminal\n");
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
Packit Service 31306d
    (void)session;
Packit Service 31306d
    (void)channel;
Packit Service 31306d
    (void)userdata;
Packit Service 31306d
    printf("Allocated shell\n");
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
struct ssh_channel_callbacks_struct channel_cb = {
Packit Service 31306d
    .channel_pty_request_function = pty_request,
Packit Service 31306d
    .channel_shell_request_function = shell_request
Packit Service 31306d
};
Packit Service 31306d
Packit Service 31306d
static ssh_channel new_session_channel(ssh_session session, void *userdata){
Packit Service 31306d
    (void) session;
Packit Service 31306d
    (void) userdata;
Packit Service 31306d
    if(chan != NULL)
Packit Service 31306d
        return NULL;
Packit Service 31306d
    printf("Allocated session channel\n");
Packit Service 31306d
    chan = ssh_channel_new(session);
Packit Service 31306d
    ssh_callbacks_init(&channel_cb);
Packit Service 31306d
    ssh_set_channel_callbacks(chan, &channel_cb);
Packit Service 31306d
    return chan;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_ARGP_H
Packit Service 31306d
const char *argp_program_version = "libssh server example "
Packit Service 31306d
SSH_STRINGIFY(LIBSSH_VERSION);
Packit Service 31306d
const char *argp_program_bug_address = "<libssh@libssh.org>";
Packit Service 31306d
Packit Service 31306d
/* Program documentation. */
Packit Service 31306d
static char doc[] = "libssh -- a Secure Shell protocol implementation";
Packit Service 31306d
Packit Service 31306d
/* A description of the arguments we accept. */
Packit Service 31306d
static char args_doc[] = "BINDADDR";
Packit Service 31306d
Packit Service 31306d
/* The options we understand. */
Packit Service 31306d
static struct argp_option options[] = {
Packit Service 31306d
    {
Packit Service 31306d
        .name  = "port",
Packit Service 31306d
        .key   = 'p',
Packit Service 31306d
        .arg   = "PORT",
Packit Service 31306d
        .flags = 0,
Packit Service 31306d
        .doc   = "Set the port to bind.",
Packit Service 31306d
        .group = 0
Packit Service 31306d
    },
Packit Service 31306d
    {
Packit Service 31306d
        .name  = "hostkey",
Packit Service 31306d
        .key   = 'k',
Packit Service 31306d
        .arg   = "FILE",
Packit Service 31306d
        .flags = 0,
Packit Service 31306d
        .doc   = "Set the host key.",
Packit Service 31306d
        .group = 0
Packit Service 31306d
    },
Packit Service 31306d
    {
Packit Service 31306d
        .name  = "dsakey",
Packit Service 31306d
        .key   = 'd',
Packit Service 31306d
        .arg   = "FILE",
Packit Service 31306d
        .flags = 0,
Packit Service 31306d
        .doc   = "Set the dsa key.",
Packit Service 31306d
        .group = 0
Packit Service 31306d
    },
Packit Service 31306d
    {
Packit Service 31306d
        .name  = "rsakey",
Packit Service 31306d
        .key   = 'r',
Packit Service 31306d
        .arg   = "FILE",
Packit Service 31306d
        .flags = 0,
Packit Service 31306d
        .doc   = "Set the rsa key.",
Packit Service 31306d
        .group = 0
Packit Service 31306d
    },
Packit Service 31306d
    {
Packit Service 31306d
        .name  = "verbose",
Packit Service 31306d
        .key   = 'v',
Packit Service 31306d
        .arg   = NULL,
Packit Service 31306d
        .flags = 0,
Packit Service 31306d
        .doc   = "Get verbose output.",
Packit Service 31306d
        .group = 0
Packit Service 31306d
    },
Packit Service 31306d
    {NULL, 0, NULL, 0, NULL, 0}
Packit Service 31306d
};
Packit Service 31306d
Packit Service 31306d
/* Parse a single option. */
Packit Service 31306d
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
Packit Service 31306d
    /* Get the input argument from argp_parse, which we
Packit Service 31306d
     * know is a pointer to our arguments structure.
Packit Service 31306d
     */
Packit Service 31306d
    ssh_bind sshbind = state->input;
Packit Service 31306d
Packit Service 31306d
    switch (key) {
Packit Service 31306d
        case 'p':
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
Packit Service 31306d
            break;
Packit Service 31306d
        case 'd':
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
Packit Service 31306d
            break;
Packit Service 31306d
        case 'k':
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
Packit Service 31306d
            break;
Packit Service 31306d
        case 'r':
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
Packit Service 31306d
            break;
Packit Service 31306d
        case 'v':
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
Packit Service 31306d
            break;
Packit Service 31306d
        case ARGP_KEY_ARG:
Packit Service 31306d
            if (state->arg_num >= 1) {
Packit Service 31306d
                /* Too many arguments. */
Packit Service 31306d
                argp_usage (state);
Packit Service 31306d
            }
Packit Service 31306d
            ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
Packit Service 31306d
            break;
Packit Service 31306d
        case ARGP_KEY_END:
Packit Service 31306d
            if (state->arg_num < 1) {
Packit Service 31306d
                /* Not enough arguments. */
Packit Service 31306d
                argp_usage (state);
Packit Service 31306d
            }
Packit Service 31306d
            break;
Packit Service 31306d
        default:
Packit Service 31306d
            return ARGP_ERR_UNKNOWN;
Packit Service 31306d
    }
Packit Service 31306d
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
/* Our argp parser. */
Packit Service 31306d
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
Packit Service 31306d
#endif /* HAVE_ARGP_H */
Packit Service 31306d
Packit Service 31306d
int main(int argc, char **argv){
Packit Service 31306d
    ssh_session session;
Packit Service 31306d
    ssh_bind sshbind;
Packit Service 31306d
    ssh_event mainloop;
Packit Service 31306d
    struct ssh_server_callbacks_struct cb = {
Packit Service 31306d
        .userdata = NULL,
Packit Service 31306d
        .auth_password_function = auth_password,
Packit Service 31306d
        .auth_gssapi_mic_function = auth_gssapi_mic,
Packit Service 31306d
        .channel_open_request_session_function = new_session_channel
Packit Service 31306d
    };
Packit Service 31306d
Packit Service 31306d
    char buf[2048];
Packit Service 31306d
    int i;
Packit Service 31306d
    int r;
Packit Service 31306d
Packit Service 31306d
    sshbind=ssh_bind_new();
Packit Service 31306d
    session=ssh_new();
Packit Service 31306d
Packit Service 31306d
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
Packit Service 31306d
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
Packit Service 31306d
Packit Service 31306d
#ifdef HAVE_ARGP_H
Packit Service 31306d
    /*
Packit Service 31306d
     * Parse our arguments; every option seen by parse_opt will
Packit Service 31306d
     * be reflected in arguments.
Packit Service 31306d
     */
Packit Service 31306d
    argp_parse (&argp, argc, argv, 0, 0, sshbind);
Packit Service 31306d
#else
Packit Service 31306d
    (void) argc;
Packit Service 31306d
    (void) argv;
Packit Service 31306d
#endif
Packit Service 31306d
Packit Service 31306d
    if(ssh_bind_listen(sshbind)<0){
Packit Service 31306d
        printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
Packit Service 31306d
        return 1;
Packit Service 31306d
    }
Packit Service 31306d
    r=ssh_bind_accept(sshbind,session);
Packit Service 31306d
    if(r==SSH_ERROR){
Packit Service 31306d
        printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
Packit Service 31306d
        return 1;
Packit Service 31306d
    }
Packit Service 31306d
    ssh_callbacks_init(&cb;;
Packit Service 31306d
    ssh_set_server_callbacks(session, &cb;;
Packit Service 31306d
Packit Service 31306d
    if (ssh_handle_key_exchange(session)) {
Packit Service 31306d
        printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
Packit Service 31306d
        return 1;
Packit Service 31306d
    }
Packit Service 31306d
    ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
Packit Service 31306d
    mainloop = ssh_event_new();
Packit Service 31306d
    ssh_event_add_session(mainloop, session);
Packit Service 31306d
Packit Service 31306d
    while (!(authenticated && chan != NULL)){
Packit Service 31306d
        if(error)
Packit Service 31306d
            break;
Packit Service 31306d
        r = ssh_event_dopoll(mainloop, -1);
Packit Service 31306d
        if (r == SSH_ERROR){
Packit Service 31306d
            printf("Error : %s\n",ssh_get_error(session));
Packit Service 31306d
            ssh_disconnect(session);
Packit Service 31306d
            return 1;
Packit Service 31306d
        }
Packit Service 31306d
    }
Packit Service 31306d
    if(error){
Packit Service 31306d
        printf("Error, exiting loop\n");
Packit Service 31306d
    } else
Packit Service 31306d
        printf("Authenticated and got a channel\n");
Packit Service 31306d
    do{
Packit Service 31306d
        i=ssh_channel_read(chan,buf, 2048, 0);
Packit Service 31306d
        if(i>0) {
Packit Service 31306d
            ssh_channel_write(chan, buf, i);
Packit Service 31306d
            if (write(1,buf,i) < 0) {
Packit Service 31306d
                printf("error writing to buffer\n");
Packit Service 31306d
                return 1;
Packit Service 31306d
            }
Packit Service 31306d
            if (buf[0] == '\x0d') {
Packit Service 31306d
                if (write(1, "\n", 1) < 0) {
Packit Service 31306d
                    printf("error writing to buffer\n");
Packit Service 31306d
                    return 1;
Packit Service 31306d
                }
Packit Service 31306d
                ssh_channel_write(chan, "\n", 1);
Packit Service 31306d
            }
Packit Service 31306d
        }
Packit Service 31306d
    } while (i>0);
Packit Service 31306d
    ssh_disconnect(session);
Packit Service 31306d
    ssh_bind_free(sshbind);
Packit Service 31306d
    ssh_finalize();
Packit Service 31306d
    return 0;
Packit Service 31306d
}
Packit Service 31306d