From d8e2024607f77546bd0bccbf93edc41b39701027 Mon Sep 17 00:00:00 2001 From: mar Date: Tue, 25 Aug 1992 14:42:50 +0000 Subject: [PATCH] Initial revision --- update/config.c | 130 +++++++++++++++++++++++++++++ update/moira.conf | 17 ++++ update/update_test.c | 195 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 update/config.c create mode 100644 update/moira.conf create mode 100644 update/update_test.c diff --git a/update/config.c b/update/config.c new file mode 100644 index 00000000..083e1fd6 --- /dev/null +++ b/update/config.c @@ -0,0 +1,130 @@ +/* $Header$ + * + * Routines to handle configuration file for Moira's update_server. + * These routines must load the file into memory rather than parse + * it each time as one of the things the server may do is chroot() + * itself. + * + * (c) Copyright 1992 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * . + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define CONFIG_FILE "/etc/athena/moira.conf" + +/* Variables currently supported: + * chroot directory daemon will run chrooted to this directory + * user username daemon will run with this user's uid + * port portname daemon will listen on this port number + * nofork server stays in foreground & logs to stdout + * auth krbname this user is authorized to connect + * noclobber will not overwrite existing files + * noexec will not execute instructions received + */ + +static char *config_buf = NULL; +static char **config_keys, **config_values; + + +static init() +{ + int fd, count = 0; + struct stat st; + char *p, *start; + + /* Only execute once */ + if (config_buf) return(MR_SUCCESS); + + fd = open(CONFIG_FILE, O_RDONLY, 0); + if (fd < 0) { + config_buf = ""; + config_keys = (char **)malloc(sizeof(char *) * 2); + config_keys[0] = config_keys[1] = NULL; + return(MR_SUCCESS); + } + if (fstat(fd, &st) < 0) { + return(MR_INTERNAL); + } + config_buf = (char *) malloc(st.st_size + 2); + if (config_buf == NULL) { + return(MR_NO_MEM); + } + if (read(fd, config_buf, st.st_size) < st.st_size) { + free(config_buf); + config_buf = NULL; + return(MR_INTERNAL); + } + config_buf[st.st_size] = '\0'; + + for (p = config_buf; *p; p++) + if (*p == '\n') count++; + count++; + config_keys = (char **)malloc(count * sizeof(char *)); + config_values = (char **)malloc(count * sizeof(char *)); + if (config_keys == NULL || config_values == NULL) { + free(config_buf); + config_buf = NULL; + return(MR_NO_MEM); + } + count = 0; + for (p = start = config_buf; *p; p++) { + if (*p != '\n') + continue; + *p++ = '\0'; + config_keys[count++] = start; + start = p; + if (!*p) break; + } + config_keys[count] = NULL; + for (count = 0; config_keys[count]; count++) { + config_values[count] = ""; + for (p = config_keys[count]; *p; p++) + if (isspace(*p)) { + *p++ = '\0'; + while (*p && isspace(*p)) p++; + config_values[count] = p; + } + } + return(MR_SUCCESS); +} + + +/* Given a key, lookup the associated value. + * Returns "" on a key without a value, NULL on a non-existant key. + * If a key appears multiple times, successive calls will cycle through + * the possible values. + */ + +char *config_lookup(key) +char *key; +{ + static int i = 0; + int start; + + if (init() != MR_SUCCESS) + return(NULL); + + start = i++; + if (config_keys[i] == NULL) i = 0; + + do { + if (!strcasecmp(key, config_keys[i])) + return(config_values[i]); + if (config_keys[++i] == NULL) + i = 0; + } while (i != start); + + if (!strcasecmp(key, config_keys[i])) + return(config_values[i]); + + return(NULL); +} diff --git a/update/moira.conf b/update/moira.conf new file mode 100644 index 00000000..60e164da --- /dev/null +++ b/update/moira.conf @@ -0,0 +1,17 @@ +# Configuration for the Moira update_server +# uncomment lines as appropriate + +# Specifies which UID the server runs as (default root) +user root +# Restricts to a subset of the filesystem heirarchry +# chroot /tmp +# Don't let the server fork (debugging only) +# nofork +# No existing files will be overwritten +# noclobber +# Do not allow the exec command +# noexec +# List of users authorized to connect (default sms@ATHENA.MIT.EDU only) +auth sms@ATHENA.MIT.EDU +# auth rcmd.moira@ATHENA.MIT.EDU +# auth mar.root@ATHENA.MIT.EDU diff --git a/update/update_test.c b/update/update_test.c new file mode 100644 index 00000000..978dafb1 --- /dev/null +++ b/update/update_test.c @@ -0,0 +1,195 @@ +/* $Header$ + * + * Test client for update_server protocol. + * + * Reads commands from the command line: + * test host [commands...] + * -s file file sends file to host + * -i file sends instruction file to host + * -x file executes instructions + * -n nop + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +CONNECTION conn; +char *whoami; + + +main(argc, argv) +int argc; +char **argv; +{ + char *host, service_address[256], *file, *rfile, buf[256]; + int code, i, count=0; + + whoami = argv[0]; + initialize_sms_error_table(); + initialize_krb_error_table(); + gdb_init(); + + if (argc < 2) usage(); + host = argv[1]; + + sprintf(service_address, "%s:%s", host, SERVICE_NAME); + conn = start_server_connection(service_address, ""); + if (!conn || (connection_status(conn) == CON_STOPPED)) { + com_err(whoami, connection_errno(conn), + " can't connect to update %s", service_address); + return(MR_CANT_CONNECT); + } + code = send_auth(host); + if (code) { + com_err(whoami, code, " authorization attempt failed"); + } + + for (i = 2; i < argc; i++) { + if (argv[i][0] != '-') usage(); + switch (argv[i][1]) { + case 's': + if (i+2 >= argc) usage(); + file = argv[++i]; + rfile = argv[++i]; + fprintf(stderr, "Sending file %s to %s as %s\n", file, host, rfile); + send_file(file, rfile); + break; + case 'i': + if (i+1 >= argc) usage(); + file = argv[++i]; + strcpy(buf, "/tmp/moira-updateXXXXX"); + mktemp(buf); + fprintf(stderr, "Sending instructions %s to %s as %s\n", + file, host, buf); + send_file(file, buf); + break; + case 'I': + if (i+2 >= argc) usage(); + file = argv[++i]; + rfile = argv[++i]; + strcpy(buf, rfile); + fprintf(stderr, "Sending instructions %s to %s as %s\n", + file, host, buf); + send_file(file, buf); + break; + case 'x': + fprintf(stderr, "Executing instructions %s on %s\n", buf, host); + code = execute(buf); + if (code) com_err(whoami, code, "executing"); + break; + case 'X': + if (i+1 >= argc) usage(); + file = argv[++i]; + fprintf(stderr, "Executing instructions %s on %s\n", file, host); + code = execute(file); + if (code) com_err(whoami, code, "executing"); + break; + case 'n': + break; + default: + usage(); + } + } + send_quit(); + conn = sever_connection(conn); + exit(code); +} + +usage() +{ + fprintf(stderr, "Usage: test host [commands...]\n"); + fprintf(stderr, " Commands are:\n"); + fprintf(stderr, "\t-s srcfile dstfile\tsends file\n"); + fprintf(stderr, "\t-i srcfile\t\tsends instructions\n"); + fprintf(stderr, "\t-I srcfile dstfile\tsends instructions\n"); + fprintf(stderr, "\t-x\t\texecutes last instructions\n"); + fprintf(stderr, "\t-X file\t\texecutes file\n"); + exit(1); +} + +static +send_auth(host_name) +char *host_name; +{ + KTEXT_ST ticket_st; + KTEXT ticket = &ticket_st; + STRING data; + register int code; + int response; + + code = get_mr_update_ticket(host_name, ticket); + if (code) { + return(code); + } + STRING_DATA(data) = "AUTH_001"; + MAX_STRING_SIZE(data) = 9; + code = send_object(conn, (char *)&data, STRING_T); + if (code) { + return(connection_errno(conn)); + } + code = receive_object(conn, (char *)&response, INTEGER_T); + if (code) { + return(connection_errno(conn)); + } + if (response) { + return(response); + } + STRING_DATA(data) = (char *)ticket->dat; + MAX_STRING_SIZE(data) = ticket->length; + code = send_object(conn, (char *)&data, STRING_T); + if (code) { + return(connection_errno(conn)); + } + code = receive_object(conn, (char *)&response, INTEGER_T); + if (code) { + return(connection_errno(conn)); + } + if (response) { + com_err(whoami, response, "Permission to connect denied"); + return(response); + } + return(MR_SUCCESS); +} + +static +execute(path) + char *path; +{ + int response; + STRING data; + register int code; + + string_alloc(&data, BUFSIZ); + sprintf(STRING_DATA(data), "EXEC_002 %s", path); + code = send_object(conn, (char *)&data, STRING_T); + if (code) + return(connection_errno(conn)); + code = receive_object(conn, (char *)&response, INTEGER_T); + if (code) + return(connection_errno(conn)); + if (response) + return(response); + return(MR_SUCCESS); +} + +send_quit() +{ + STRING str; + if (!conn) + return; + string_alloc(&str, 5); + (void) strcpy(STRING_DATA(str), "quit"); + (void) send_object(conn, (char *)&str, STRING_T); + string_free(&str); +} -- 2.45.2