| 1 | /* |
|---|
| 2 | * tokens test suite. |
|---|
| 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 <fcntl.h> |
|---|
| 17 | #include <sys/stat.h> |
|---|
| 18 | #include <sys/time.h> |
|---|
| 19 | #include <sys/wait.h> |
|---|
| 20 | |
|---|
| 21 | #include <tests/tap/basic.h> |
|---|
| 22 | #include <util/util.h> |
|---|
| 23 | |
|---|
| 24 | /* A token for testing. */ |
|---|
| 25 | static const char token[] = { 3, 0, 0, 0, 5, 'h', 'e', 'l', 'l', 'o' }; |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | /* |
|---|
| 29 | * Create a server socket, wait for a connection, and return the connected |
|---|
| 30 | * socket. |
|---|
| 31 | */ |
|---|
| 32 | static int |
|---|
| 33 | create_server(void) |
|---|
| 34 | { |
|---|
| 35 | int fd, conn, marker; |
|---|
| 36 | struct sockaddr_in saddr; |
|---|
| 37 | int on = 1; |
|---|
| 38 | |
|---|
| 39 | saddr.sin_family = AF_INET; |
|---|
| 40 | saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|---|
| 41 | saddr.sin_port = htons(14373); |
|---|
| 42 | fd = socket(AF_INET, SOCK_STREAM, 0); |
|---|
| 43 | if (fd < 0) |
|---|
| 44 | sysbail("error creating socket"); |
|---|
| 45 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); |
|---|
| 46 | if (bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) |
|---|
| 47 | sysbail("error binding socket"); |
|---|
| 48 | if (listen(fd, 1) < 0) |
|---|
| 49 | sysbail("error listening on socket"); |
|---|
| 50 | marker = open("server-ready", O_CREAT | O_TRUNC, 0666); |
|---|
| 51 | if (marker < 0) |
|---|
| 52 | sysbail("cannot create marker file"); |
|---|
| 53 | conn = accept(fd, NULL, 0); |
|---|
| 54 | if (conn < 0) |
|---|
| 55 | sysbail("error accepting connection"); |
|---|
| 56 | return conn; |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | /* |
|---|
| 61 | * Create a client socket, it for a connection, and return the connected |
|---|
| 62 | * socket. |
|---|
| 63 | */ |
|---|
| 64 | static int |
|---|
| 65 | create_client(void) |
|---|
| 66 | { |
|---|
| 67 | int fd; |
|---|
| 68 | struct sockaddr_in saddr; |
|---|
| 69 | struct timeval tv; |
|---|
| 70 | |
|---|
| 71 | saddr.sin_family = AF_INET; |
|---|
| 72 | saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|---|
| 73 | saddr.sin_port = htons(14373); |
|---|
| 74 | fd = socket(AF_INET, SOCK_STREAM, 0); |
|---|
| 75 | if (fd < 0) |
|---|
| 76 | sysbail("error creating socket"); |
|---|
| 77 | alarm(1); |
|---|
| 78 | while (access("server-ready", F_OK) != 0) { |
|---|
| 79 | tv.tv_sec = 0; |
|---|
| 80 | tv.tv_usec = 10000; |
|---|
| 81 | select(0, NULL, NULL, NULL, &tv); |
|---|
| 82 | } |
|---|
| 83 | alarm(0); |
|---|
| 84 | if (connect(fd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) |
|---|
| 85 | sysbail("error connecting"); |
|---|
| 86 | return fd; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | /* |
|---|
| 91 | * Send a hand-constructed token to a file descriptor. |
|---|
| 92 | */ |
|---|
| 93 | static void |
|---|
| 94 | send_hand_token(int fd) |
|---|
| 95 | { |
|---|
| 96 | xwrite(fd, token, sizeof(token)); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | /* |
|---|
| 101 | * Send a token via token_send to a file descriptor. |
|---|
| 102 | */ |
|---|
| 103 | static void |
|---|
| 104 | send_regular_token(int fd) |
|---|
| 105 | { |
|---|
| 106 | gss_buffer_desc buffer; |
|---|
| 107 | |
|---|
| 108 | buffer.value = xmalloc(5); |
|---|
| 109 | memcpy(buffer.value, "hello", 5); |
|---|
| 110 | buffer.length = 5; |
|---|
| 111 | token_send(fd, 3, &buffer); |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | |
|---|
| 115 | int |
|---|
| 116 | main(void) |
|---|
| 117 | { |
|---|
| 118 | pid_t child; |
|---|
| 119 | int server, client, status, flags; |
|---|
| 120 | char buffer[20]; |
|---|
| 121 | ssize_t length; |
|---|
| 122 | gss_buffer_desc result; |
|---|
| 123 | |
|---|
| 124 | alarm(2); |
|---|
| 125 | |
|---|
| 126 | plan(10); |
|---|
| 127 | if (chdir(getenv("BUILD")) < 0) |
|---|
| 128 | sysbail("can't chdir to BUILD"); |
|---|
| 129 | |
|---|
| 130 | unlink("server-ready"); |
|---|
| 131 | child = fork(); |
|---|
| 132 | if (child < 0) |
|---|
| 133 | sysbail("cannot fork"); |
|---|
| 134 | else if (child == 0) { |
|---|
| 135 | server = create_server(); |
|---|
| 136 | send_regular_token(server); |
|---|
| 137 | exit(0); |
|---|
| 138 | } else { |
|---|
| 139 | client = create_client(); |
|---|
| 140 | length = read(client, buffer, 12); |
|---|
| 141 | is_int(10, length, "received token has correct length"); |
|---|
| 142 | ok(memcmp(buffer, token, 10) == 0, "...and correct data"); |
|---|
| 143 | waitpid(child, NULL, 0); |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | unlink("server-ready"); |
|---|
| 147 | child = fork(); |
|---|
| 148 | if (child < 0) |
|---|
| 149 | sysbail("cannot fork"); |
|---|
| 150 | else if (child == 0) { |
|---|
| 151 | server = create_server(); |
|---|
| 152 | send_hand_token(server); |
|---|
| 153 | exit(0); |
|---|
| 154 | } else { |
|---|
| 155 | client = create_client(); |
|---|
| 156 | status = token_recv(client, &flags, &result, 5); |
|---|
| 157 | is_int(TOKEN_OK, status, "received hand-rolled token"); |
|---|
| 158 | is_int(3, flags, "...with right flags"); |
|---|
| 159 | is_int(5, result.length, "...and right length"); |
|---|
| 160 | ok(memcmp(result.value, "hello", 5) == 0, "...and right data"); |
|---|
| 161 | waitpid(child, NULL, 0); |
|---|
| 162 | } |
|---|
| 163 | |
|---|
| 164 | unlink("server-ready"); |
|---|
| 165 | child = fork(); |
|---|
| 166 | if (child < 0) |
|---|
| 167 | sysbail("cannot fork"); |
|---|
| 168 | else if (child == 0) { |
|---|
| 169 | server = create_server(); |
|---|
| 170 | xwrite(server, "\0\0\0\0\1", 5); |
|---|
| 171 | exit(0); |
|---|
| 172 | } else { |
|---|
| 173 | client = create_client(); |
|---|
| 174 | status = token_recv(client, &flags, &result, 200); |
|---|
| 175 | is_int(TOKEN_FAIL_INVALID, status, "receive invalid token"); |
|---|
| 176 | waitpid(child, NULL, 0); |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | unlink("server-ready"); |
|---|
| 180 | child = fork(); |
|---|
| 181 | if (child < 0) |
|---|
| 182 | sysbail("cannot fork"); |
|---|
| 183 | else if (child == 0) { |
|---|
| 184 | server = create_server(); |
|---|
| 185 | send_hand_token(server); |
|---|
| 186 | exit(0); |
|---|
| 187 | } else { |
|---|
| 188 | client = create_client(); |
|---|
| 189 | status = token_recv(client, &flags, &result, 4); |
|---|
| 190 | is_int(TOKEN_FAIL_LARGE, status, "receive too-large token"); |
|---|
| 191 | waitpid(child, NULL, 0); |
|---|
| 192 | } |
|---|
| 193 | |
|---|
| 194 | unlink("server-ready"); |
|---|
| 195 | child = fork(); |
|---|
| 196 | if (child < 0) |
|---|
| 197 | sysbail("cannot fork"); |
|---|
| 198 | else if (child == 0) { |
|---|
| 199 | server = create_server(); |
|---|
| 200 | close(server); |
|---|
| 201 | exit(0); |
|---|
| 202 | } else { |
|---|
| 203 | client = create_client(); |
|---|
| 204 | status = token_recv(client, &flags, &result, 4); |
|---|
| 205 | is_int(TOKEN_FAIL_EOF, status, "receive end of file"); |
|---|
| 206 | waitpid(child, NULL, 0); |
|---|
| 207 | } |
|---|
| 208 | unlink("server-ready"); |
|---|
| 209 | |
|---|
| 210 | /* Special test for error handling when sending tokens. */ |
|---|
| 211 | server = open("/dev/full", O_RDWR); |
|---|
| 212 | if (server < 0) |
|---|
| 213 | skip("/dev/full not available"); |
|---|
| 214 | else { |
|---|
| 215 | result.value = xmalloc(5); |
|---|
| 216 | memcpy(result.value, "hello", 5); |
|---|
| 217 | result.length = 5; |
|---|
| 218 | status = token_send(server, 3, &result); |
|---|
| 219 | free(result.value); |
|---|
| 220 | is_int(TOKEN_FAIL_SOCKET, status, "can't send due to system error"); |
|---|
| 221 | close(server); |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | return 0; |
|---|
| 225 | } |
|---|