source: web/old/remctl-2.14/tests/server/accept-t.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * Test suite for the server connection negotiation code.
3 *
4 * Written by Russ Allbery <rra@stanford.edu>
5 * Copyright 2006, 2007, 2009
6 *     Board of Trustees, Leland Stanford Jr. University
7 *
8 * See LICENSE for licensing terms.
9 */
10
11#include <config.h>
12#include <portable/system.h>
13#include <portable/gssapi.h>
14#include <portable/socket.h>
15
16#include <sys/wait.h>
17
18#include <server/internal.h>
19#include <tests/tap/basic.h>
20#include <tests/tap/kerberos.h>
21#include <util/util.h>
22
23
24/*
25 * Open a new connection to a server, taking the protocol version and
26 * principal to use.  1 indicates protocol version 1 the whole way, 2
27 * indicates version 2 from the start, and 0 starts with version 2, goes back
28 * to version 1, and then goes to version 2.
29 */
30static void
31make_connection(int protocol, const char *principal)
32{
33    struct sockaddr_in saddr;
34    int fd, flags;
35    gss_buffer_desc send_tok, recv_tok, name_buffer, *token_ptr;
36    gss_buffer_desc empty_token = { 0, (void *) "" };
37    gss_name_t name;
38    gss_ctx_id_t gss_context;
39    OM_uint32 major, minor, init_minor, gss_flags;
40    static const OM_uint32 req_gss_flags
41        = (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_CONF_FLAG
42           | GSS_C_INTEG_FLAG);
43
44    /* Connect. */
45    saddr.sin_family = AF_INET;
46    saddr.sin_port = htons(14373);
47    saddr.sin_addr.s_addr = INADDR_ANY;
48    fd = socket(AF_INET, SOCK_STREAM, 0);
49    if (fd < 0)
50        sysdie("error creating socket");
51    if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
52        sysdie("error connecting");
53
54    /* Import the name into target_name. */
55    name_buffer.value = (char *) principal;
56    name_buffer.length = strlen(principal) + 1;
57    major = gss_import_name(&minor, &name_buffer, GSS_C_NT_USER_NAME, &name);
58    if (major != GSS_S_COMPLETE)
59        die("cannot import name");
60
61    /* Send the initial negotiation token. */
62    flags = TOKEN_NOOP | TOKEN_CONTEXT_NEXT;
63    if (protocol == 0 || protocol > 1)
64        flags |= TOKEN_PROTOCOL;
65    if (token_send(fd, flags, &empty_token) != TOKEN_OK)
66        sysdie("failure sending token");
67
68    /* Perform the context-establishment loop. */
69    token_ptr = GSS_C_NO_BUFFER;
70    gss_context = GSS_C_NO_CONTEXT;
71    do {
72        major = gss_init_sec_context(&init_minor, GSS_C_NO_CREDENTIAL, 
73                    &gss_context, name, (const gss_OID) GSS_KRB5_MECHANISM,
74                    req_gss_flags, 0, NULL, token_ptr, NULL, &send_tok,
75                    &gss_flags, NULL);
76        if (token_ptr != GSS_C_NO_BUFFER)
77            gss_release_buffer(&minor, &recv_tok);
78        if (send_tok.length != 0) {
79            flags = TOKEN_CONTEXT;
80            if (protocol > 1)
81                flags |= TOKEN_PROTOCOL;
82            if (protocol == 0)
83                protocol = 2;
84            if (token_send(fd, flags, &send_tok) != TOKEN_OK)
85                sysdie("failure sending token");
86        }
87        gss_release_buffer(&minor, &send_tok);
88        if (major != GSS_S_COMPLETE && major != GSS_S_CONTINUE_NEEDED)
89            die("failure initializing context");
90        if (major == GSS_S_CONTINUE_NEEDED) {
91            if (token_recv(fd, &flags, &recv_tok, 64 * 1024) != TOKEN_OK)
92                sysdie("failure receiving token");
93            token_ptr = &recv_tok;
94        }
95    } while (major == GSS_S_CONTINUE_NEEDED);
96
97    /* All done.  Don't bother cleaning up, just exit. */
98    exit(0);
99}
100
101
102int
103main(void)
104{
105    char *principal;
106    int s, fd, protocol;
107    pid_t child;
108    struct sockaddr_in saddr;
109    struct client *client;
110    int on = 1;
111
112    /* Unless we have Kerberos available, we can't really do anything. */
113    principal = kerberos_setup();
114    if (principal == NULL)
115        skip_all("Kerberos tests not configured");
116    plan(2 * 3);
117
118    /* Set up address to which we're going to bind and start listening.. */
119    saddr.sin_family = AF_INET;
120    saddr.sin_port = htons(14373);
121    saddr.sin_addr.s_addr = INADDR_ANY;
122    s = socket(AF_INET, SOCK_STREAM, 0);
123    if (s < 0)
124        sysbail("error creating socket");
125    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
126    if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
127        sysbail("error binding socket");
128    if (listen(s, 1) < 0)
129        sysbail("error listening to socket");
130
131    /*
132     * We're going to try this three times, for each of the three possible
133     * different protocol negotiation behaviors that accept_connection can
134     * test.  Each time, we're going to check that we got a context and that
135     * we negotiated the appropriate protocol.
136     */
137    for (protocol = 0; protocol <= 2; protocol++) {
138        child = fork();
139        if (child < 0)
140            sysbail("cannot fork");
141        else if (child == 0)
142            make_connection(protocol, principal);
143        alarm(1);
144        fd = accept(s, NULL, 0);
145        if (fd < 0)
146            sysbail("error accepting connection");
147        alarm(0);
148        client = server_new_client(fd, GSS_C_NO_CREDENTIAL);
149        ok(client != NULL, "accept client with protocol %d", protocol);
150        if (client == NULL)
151            ok(0, "negotiated right protocol");
152        else
153            is_int((protocol < 2) ? 1 : 2, client->protocol,
154                   "negotiated right protocol");
155        server_free_client(client);
156        waitpid(child, NULL, 0);
157    }
158
159    return 0;
160}
Note: See TracBrowser for help on using the repository browser.