コード例 #1
0
ファイル: source-ip-t.c プロジェクト: moretension/remctl
int
main(void)
{
    struct kerberos_config *config;
    const char *err;
    struct remctl *r;
    struct remctl_output *output;
    const char *command[] = { "test", "env", "REMOTE_ADDR", NULL };

    /* Set up Kerberos and remctld. */
    config = kerberos_setup(TAP_KRB_NEEDS_KEYTAB);
    remctld_start(config, "data/conf-simple", (char *) 0);

    plan(10);

    /* Successful connection to 127.0.0.1. */
    r = remctl_new();
    ok(r != NULL, "remctl_new");
    ok(remctl_set_source_ip(r, "127.0.0.1"), "remctl_set_source_ip");
    ok(remctl_open(r, "127.0.0.1", 14373, config->principal),
       "remctl_open to 127.0.0.1");
    ok(remctl_command(r, command), "remctl_command");
    output = remctl_output(r);
    ok(output != NULL, "remctl_output");
    if (output == NULL)
        ok_block(3, 0, "remctl_output failed");
    else {
        is_int(REMCTL_OUT_OUTPUT, output->type, "output token");
        ok(memcmp("127.0.0.1\n", output->data, strlen("127.0.0.1\n")) == 0,
           "correct IP address");
        is_int(strlen("127.0.0.1\n"), output->length, "correct length");
    }

    /* Failed connection to ::1. */
    ok(!remctl_open(r, "::1", 14373, config->principal), "remctl_open to ::1");
    err = remctl_error(r);
    diag("error: %s", err);
    ok(((strncmp("cannot connect to ::1 (port 14373): ", err,
                strlen("cannot connect to ::1 (port 14373): ")) == 0)
        || (strncmp("unknown host ::1: ", err,
                    strlen("unknown host ::1: ")) == 0)),
       "failed with correct error");

    remctl_close(r);
    return 0;
}
コード例 #2
0
ファイル: empty-t.c プロジェクト: mloar/remctl
int
main(void)
{
    struct kerberos_config *config;
    struct remctl *r;
    struct remctl_output *output;
    char *tmpdir, *confpath;
    FILE *conf;
    const char *test[] = { "test", "test", NULL };

    /* Unless we have Kerberos available, we can't really do anything. */
    config = kerberos_setup(TAP_KRB_NEEDS_KEYTAB);

    /* Write out our empty configuration file. */
    tmpdir = test_tmpdir();
    basprintf(&confpath, "%s/conf-empty", tmpdir);
    conf = fopen(confpath, "w");
    if (conf == NULL)
        sysbail("cannot create %s", confpath);
    fclose(conf);

    /* Now we can start remctl with our temporary configuration file. */
    remctld_start(config, "tmp/conf-empty", NULL);

    plan(7);

    /* Test that we get a valid UNKNOWN_COMMAND error. */
    r = remctl_new();
    ok(remctl_open(r, "localhost", 14373, config->principal), "remctl_open");
    ok(remctl_command(r, test), "remctl_command");
    output = remctl_output(r);
    ok(output != NULL, "first output token is not null");
    if (output == NULL)
        ok_block(4, 0, "...and has correct content");
    else {
        is_int(REMCTL_OUT_ERROR, output->type, "...and is an error");
        is_int(15, output->length, "...and is right length");
        if (output->data == NULL)
            ok(0, "...and has the right error message");
        else
            ok(memcmp("Unknown command", output->data, 15) == 0,
               "...and has the right error message");
        is_int(ERROR_UNKNOWN_COMMAND, output->error, "...and error number");
    }
    remctl_close(r);
    unlink(confpath);
    free(confpath);
    test_tmpdir_free(tmpdir);
    return 0;
}
コード例 #3
0
ファイル: noop-t.c プロジェクト: mloar/remctl
int
main(void)
{
    struct kerberos_config *config;
    struct remctl *r;
    OM_uint32 major, minor;
    int flags, status;
    gss_buffer_desc tok;

    /* Unless we have Kerberos available, we can't really do anything. */
    config = kerberos_setup(TAP_KRB_NEEDS_KEYTAB);
    remctld_start(config, "data/conf-simple", NULL);

    plan(7);

    /* Open the connection to the site. */
    r = remctl_new();
    ok(r != NULL, "remctl_new");
    ok(remctl_open(r, "localhost", 14373, config->principal), "remctl_open");

    /* Send the no-op token. */
    tok.length = sizeof(token);
    tok.value = (char *) token;
    status = token_send_priv(r->fd, r->context, TOKEN_DATA | TOKEN_PROTOCOL,
                             &tok, 0, &major, &minor);
    if (status != TOKEN_OK)
        bail("cannot send token");

    /* Accept the remote token. */
    status = token_recv_priv(r->fd, r->context, &flags, &tok, 1024 * 64, 0,
                             &major, &minor);
    is_int(TOKEN_OK, status, "received token correctly");
    is_int(TOKEN_DATA | TOKEN_PROTOCOL, flags, "token had correct flags");
    is_int(2, tok.length, "token had correct length");
    is_int(3, ((char *) tok.value)[0], "protocol version is 3");
    is_int(MESSAGE_NOOP, ((char *) tok.value)[1], "no-op message");

    /* Close things out. */
    remctl_close(r);
    return 0;
}
コード例 #4
0
ファイル: ccache-t.c プロジェクト: mloar/remctl
int
main(void)
{
    struct kerberos_config *config;
    const char *cache;
    struct remctl *r;
    struct remctl_output *output;
    int status;
    const char *command[] = { "test", "test", NULL };

    /* Set up Kerberos and remctld. */
    config = kerberos_setup(TAP_KRB_NEEDS_KEYTAB);
    remctld_start(config, "data/conf-simple", (char *) 0);

    plan(12);

    /* Get the current ticket cache and then change KRB5CCNAME. */
    cache = getenv("KRB5CCNAME");
    if (cache == NULL)
        bail("failed to set KRB5CCNAME");
    putenv((char *) "KRB5CCNAME=./nonexistent-file");

    /* Connecting without setting the ticket cache should fail. */
    r = remctl_new();
    ok(r != NULL, "remctl_new");
    ok(!remctl_open(r, "127.0.0.1", 14373, config->principal),
       "remctl_open to 127.0.0.1");

    /* Set the ticket cache and connect to 127.0.0.1 and run a command. */
    status = remctl_set_ccache(r, cache);
    if (!status) {
        is_string("setting credential cache not supported", remctl_error(r),
                  "remctl_set_ccache failed with correct error");
        skip_block(9, "credential cache setting not supported");
    } else {
        ok(remctl_set_ccache(r, cache), "remctl_set_ccache");
        ok(remctl_open(r, "127.0.0.1", 14373, config->principal),
           "remctl_open to 127.0.0.1");
        ok(remctl_command(r, command), "remctl_command");
        output = remctl_output(r);
        ok(output != NULL, "remctl_output #1");
        if (output == NULL)
            ok_block(3, 0, "remctl_output failed");
        else {
            is_int(REMCTL_OUT_OUTPUT, output->type, "output token");
            ok(memcmp("hello world\n", output->data,
                      strlen("hello world\n")) == 0,
               "correct output");
            is_int(strlen("hello world\n"), output->length, "correct length");
        }
        output = remctl_output(r);
        ok(output != NULL, "remctl_output #2");
        if (output == NULL)
            ok_block(2, 0, "remctl_output failed");
        else {
            is_int(REMCTL_OUT_STATUS, output->type, "status token");
            is_int(0, output->status, "status is correct");
        }
    }
    remctl_close(r);

    return 0;
}
コード例 #5
0
ファイル: remctl.c プロジェクト: moretension/remctl
/*
 * Main routine.  Parse the arguments, open the remctl connection, send the
 * command, and then call process_response.
 */
int
main(int argc, char *argv[])
{
    int option, status;
    char *server_host;
    struct addrinfo hints, *ai;
    const char *source = NULL;
    const char *service_name = NULL;
    unsigned short port = 0;
    struct remctl *r;
    int errorcode = 0;

    /* Set up logging and identity. */
    message_program_name = "remctl";
    if (!socket_init())
        die("failed to initialize socket library");

    /*
     * Parse options.  The + tells GNU getopt to stop option parsing at the
     * first non-argument rather than proceeding on to find options anywhere.
     * Without this, it's hard to call remote programs that take options.
     * Non-GNU getopt will treat the + as a supported option, which is handled
     * below.
     */
    while ((option = getopt(argc, argv, "+b:dhp:s:v")) != EOF) {
        switch (option) {
        case 'b':
            source = optarg;
            break;
        case 'd':
            message_handlers_debug(1, message_log_stderr);
            break;
        case 'h':
            usage(0);
            break;
        case 'p':
            port = atoi(optarg);
            break;
        case 's':
            service_name = optarg;
            break;
        case 'v':
            printf("%s\n", PACKAGE_STRING);
            exit(0);
            break;
        case '+':
            fprintf(stderr, "%s: invalid option -- +\n", argv[0]);
        default:
            usage(1);
            break;
        }
    }
    argc -= optind;
    argv += optind;
    if (argc < 2)
        usage(1);
    server_host = *argv++;
    argc--;

    /*
     * If service_name isn't set, the remctl library uses host/<server>
     * (host@<server> in GSS-API parlance).  However, if the server to which
     * we're connecting is a DNS-load-balanced name, we have to be careful
     * what principal name we use.
     *
     * Ideally, we would let the GSS-API library handle this and choose
     * whether to canonicalize the <server> in the principal name based on the
     * krb5.conf rdns setting and similar configuration.  However, with DNS
     * load balancing, this still may fail.  At the time of network
     * connection, we will connect to whatever the name resolves to then.
     * After we connect, we authenticate, and the GSS-API library will then
     * separately canonicalize the hostname.  It could get a different answer
     * than we got for our network connection, leading to an authentication
     * failure.
     *
     * Therefore, if the principal isn't specified, we canonicalize the
     * hostname to which we're connecting before we connect.  Then, the
     * additional canonicalization possibly done by the GSS-API library should
     * return the same results and be consistent.
     *
     * Note that this opens the possibility of a subtle attack through DNS
     * spoofing, since both the principal used and the host to which we're
     * connecting can be changed by varying the DNS response.
     *
     * If the principal is specified explicitly, assume the user knows what
     * they're doing and don't do any of this.
     */
    if (service_name == NULL) {
        memset(&hints, 0, sizeof(hints));
        hints.ai_flags = AI_CANONNAME;
        status = getaddrinfo(server_host, NULL, &hints, &ai);
        if (status != 0)
            die("cannot resolve host %s: %s", server_host,
                gai_strerror(status));
        server_host = xstrdup(ai->ai_canonname);
        freeaddrinfo(ai);
    }

    /* Open connection. */
    r = remctl_new();
    if (r == NULL)
        sysdie("cannot initialize remctl connection");
    if (source != NULL)
        if (!remctl_set_source_ip(r, source))
            die("%s", remctl_error(r));
    if (!remctl_open(r, server_host, port, service_name))
        die("%s", remctl_error(r));

    /* Do the work. */
    if (!remctl_command(r, (const char **) argv))
        die("%s", remctl_error(r));
    if (!process_response(r, &errorcode))
        die("%s", remctl_error(r));

    /* Shut down cleanly. */
    remctl_close(r);
    socket_shutdown();
    return errorcode;
}