.PHONY: test
test: spiceterm
- #./spiceterm & remote-viewer spice://localhost:5912
- G_MESSAGES_DEBUG=all SPICE_DEBUG=1 ./spiceterm & G_MESSAGES_DEBUG=all SPICE_DEBUG=1 remote-viewer --debug 'spice://localhost?tls-port=5912' --spice-ca-file /etc/pve/pve-root-ca.pem --spice-secure-channels=all
+ #./spiceterm & remote-viewer spice://localhost:5900
+ G_MESSAGES_DEBUG=all SPICE_DEBUG=1 SPICE_TICKET=test ./spiceterm & G_MESSAGES_DEBUG=all SPICE_DEBUG=1 remote-viewer --debug 'spice://localhost?tls-port=5900' --spice-ca-file /etc/pve/pve-root-ca.pem --spice-secure-channels=all
.PHONY: distclean
distclean: clean
static char *auth_path = "/";
static char *auth_perm = "Sys.Console";
+void
+pve_auth_set_path(char *path)
+{
+ auth_path = path;
+}
+
+void
+pve_auth_set_permissions(char *perm)
+{
+ auth_perm = perm;
+}
+
static char *
urlencode(char *buf, const char *value)
{
};
spiceTerm *
-create_spiceterm(int argc, char** argv, uint32_t maxx, uint32_t maxy, guint timeout)
+spiceterm_create(uint32_t width, uint32_t height, SpiceTermOptions *opts)
{
SpiceCoreInterface *core = basic_event_loop_init();
- SpiceScreen *spice_screen = spice_screen_new(core, maxx, maxy, timeout);
+ SpiceScreen *spice_screen = spice_screen_new(core, width, height, opts);
//spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF);
spice_server_add_interface(spice_screen->server, &vt->vdagent_sin.base);
vt->screen = spice_screen;
- init_spiceterm(vt, maxx, maxy);
+ init_spiceterm(vt, width, height);
return vt;
}
};
SpiceScreen *
-spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height, guint timeout)
+spice_screen_new(SpiceCoreInterface *core, uint32_t width, uint32_t height,
+ SpiceTermOptions *opts)
{
- int port = 5912;
SpiceScreen *spice_screen = g_new0(SpiceScreen, 1);
SpiceServer* server = spice_server_new();
char *x509_key_file = "/etc/pve/local/pve-ssl.key";
char *x509_dh_file = NULL;
char *tls_ciphers = "DES-CBC3-SHA";
- gboolean use_auth = TRUE;
-
spice_screen->width = width;
spice_screen->height = height;
spice_screen->core = core;
spice_screen->server = server;
- printf("listening on port %d (secure)\n", port);
- // spice_server_set_addr();
+ if (opts->addr) {
+ printf("listening on '%s:%d' (TLS)\n", opts->addr, opts->port);
+ spice_server_set_addr(server, opts->addr, 0);
+ } else {
+ printf("listening on '*:%d' (TLS)\n", opts->port);
+ }
+
// spice_server_set_port(spice_server, port);
//spice_server_set_image_compression(server, SPICE_IMAGE_COMPRESS_OFF);
- spice_server_set_tls(server, port,
+ spice_server_set_tls(server, opts->port,
x509_cacert_file,
x509_cert_file,
x509_key_file,
x509_dh_file,
tls_ciphers);
- if (use_auth) {
- spice_server_set_sasl(server, 1);
- spice_server_set_sasl_callbacks(server, sasl_callbacks);
- } else {
+ if (opts->noauth) {
spice_server_set_noauth(server);
+ } else {
+ if (opts->sasl) {
+ spice_server_set_sasl(server, 1);
+ spice_server_set_sasl_appname(server, NULL); // enforce pve auth
+ spice_server_set_sasl_callbacks(server, sasl_callbacks);
+ } else {
+ char *ticket = getenv("SPICE_TICKET");
+ if (ticket) {
+ spice_server_set_ticket(server, ticket, 300, 0, 0);
+ }
+ }
}
int res = spice_server_init(server, core);
cursor_init();
spice_screen->conn_timeout_timer = core->timer_add(do_conn_timeout, spice_screen);
- spice_screen->core->timer_start(spice_screen->conn_timeout_timer, timeout*1000);
+ spice_screen->core->timer_start(spice_screen->conn_timeout_timer, opts->timeout*1000);
spice_server_add_interface(spice_screen->server, &spice_screen->qxl_instance.base);
#include <sys/wait.h>
#include <signal.h>
#include <locale.h>
+#include <getopt.h>
#include "spiceterm.h"
#define TERMIDCODE "[?1;2c" // vt100 ID
-#define CHECK_ARGC(argc,argv,i) if (i >= argc-1) { \
- fprintf(stderr, "ERROR: not enough arguments for: %s\n", argv[i]); \
- print_usage(NULL); \
- exit(1); \
-}
-
/* these colours are from linux kernel drivers/char/vt.c */
unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15 };
-static void
-print_usage(const char *msg)
-{
- if (msg) { fprintf(stderr, "ERROR: %s\n", msg); }
- fprintf(stderr, "USAGE: spiceterm [spiceopts] [-c command [args]]\n");
-}
-
static void
draw_char_at(spiceTerm *vt, int x, int y, gunichar2 ch, TextAttributes attrib)
{
}
}
+static void
+spiceterm_print_usage(const char *msg)
+{
+ if (msg) {
+ fprintf(stderr, "ERROR: %s\n", msg);
+ }
+ fprintf(stderr, "USAGE: spiceterm [OPTIONS] [-- command [args]]\n");
+ fprintf(stderr, " --timeout <seconds> Wait this time before aborting (default is 10 seconds)\n");
+ fprintf(stderr, " --authpath <path> Authentication path (PVE AUTH)\n");
+ fprintf(stderr, " --permission <perm> Required permissions (PVE AUTH)\n");
+ fprintf(stderr, " --port <port> Bind to port <port>\n");
+ fprintf(stderr, " --addr <addr> Bind to address <addr>\n");
+ fprintf(stderr, " --sasl Enable SASL based authentication\n");
+ fprintf(stderr, " --noauth Disable authentication\n");
+}
+
int
main (int argc, char** argv)
{
- int i;
+ int c;
char **cmdargv = NULL;
char *command = "/bin/bash"; // execute normal shell as default
int pid;
int master;
char ptyname[1024];
struct winsize dimensions;
+ SpiceTermOptions opts = {
+ .timeout = 10,
+ .port = 5900,
+ .addr = NULL,
+ .noauth = FALSE,
+ .sasl = FALSE,
+ };
g_thread_init(NULL);
- for (i = 1; i < argc; i++) {
- if (!strcmp (argv[i], "-c")) {
- command = argv[i+1];
- cmdargv = &argv[i+1];
- argc = i;
- argv[i] = NULL;
+ static struct option long_options[] = {
+ { "timeout", required_argument, 0, 't' },
+ { "authpath", required_argument, 0, 'A' },
+ { "permissions", required_argument, 0, 'P' },
+ { "port", required_argument, 0, 'p' },
+ { "addr", required_argument, 0, 'a' },
+ { "noauth", no_argument, 0, 'n' },
+ { "sasl", no_argument, 0, 's' },
+ { NULL, 0, 0, 0 },
+ };
+
+ while ((c = getopt_long(argc, argv, "nst:a:p:P:", long_options, NULL)) != -1) {
+
+ switch (c) {
+ case 'n':
+ opts.noauth = TRUE;
+ break;
+ case 's':
+ opts.sasl = TRUE;
+ break;
+ case 'A':
+ pve_auth_set_path(optarg);
+ break;
+ case 'P':
+ pve_auth_set_permissions(optarg);
+ break;
+ case 'p':
+ opts.port = atoi(optarg);
+ break;
+ case 'a':
+ opts.addr = optarg;
+ break;
+ case 't':
+ opts.timeout = atoi(optarg);
break;
+ case '?':
+ spiceterm_print_usage(NULL);
+ exit(-1);
+ break;
+ default:
+ spiceterm_print_usage("getopt returned unknown character code");
+ exit(-1);
}
}
-
- if (0) print_usage(NULL); // fixme:
-
- spiceTerm *vt = create_spiceterm (argc, argv, 744, 400, 10);
+
+ if (optind < argc) {
+ command = argv[optind+1];
+ cmdargv = &argv[optind+1];
+ }
+
+ spiceTerm *vt = spiceterm_create(744, 400, &opts);
setlocale(LC_ALL, ""); // set from environment
#define MAX_HEIGHT 1440
#define MAX_WIDTH 2560
+typedef struct SpiceTermOptions {
+ guint timeout;
+ int port;
+ char *addr;
+ gboolean noauth;
+ gboolean sasl;
+} SpiceTermOptions;
+
typedef struct SpiceScreen SpiceScreen;
typedef struct CachedImage {
void (*on_client_disconnected)(SpiceScreen *spice_screen);
};
-SpiceScreen* spice_screen_new(SpiceCoreInterface* core, uint32_t width, uint32_t height, guint timeout);
+SpiceScreen* spice_screen_new(SpiceCoreInterface* core, uint32_t width, uint32_t height, SpiceTermOptions *opts);
void spice_screen_resize(SpiceScreen *spice_screen, uint32_t width, uint32_t height);
void spice_screen_draw_char(SpiceScreen *spice_screen, int x, int y, gunichar2 ch, TextAttributes attrib);
void spiceterm_respond_data(spiceTerm *vt, int len, uint8_t *data);
void spiceterm_update_watch_mask(spiceTerm *vt, gboolean writable);
-spiceTerm *create_spiceterm(int argc, char** argv, uint32_t maxx,
- uint32_t maxy, guint timeout);
+spiceTerm *spiceterm_create(uint32_t width, uint32_t height, SpiceTermOptions *opts);
gboolean vdagent_owns_clipboard(spiceTerm *vt);
void vdagent_request_clipboard(spiceTerm *vt);
void vdagent_grab_clipboard(spiceTerm *vt);
int pve_auth_verify(const char *clientip, const char *username, const char *passwd);
-
+void pve_auth_set_path(char *path);
+void pve_auth_set_permissions(char *perm);