summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-01-25 13:27:20 -0500
committerSimo Sorce <simo@redhat.com>2012-01-25 13:27:20 -0500
commitde5ed03701330989cfbd85ba3a59bce33fceb261 (patch)
tree62a3ec25745a3f6f21c762d6ae95cb0fe7c1f522
parent2aa8a36bb350d5ce0ddeb1f3eb7011b9311f7d19 (diff)
downloadgss-proxy-de5ed03701330989cfbd85ba3a59bce33fceb261.tar.gz
gss-proxy-de5ed03701330989cfbd85ba3a59bce33fceb261.tar.xz
gss-proxy-de5ed03701330989cfbd85ba3a59bce33fceb261.zip
Improve test program
Split it into a lcient and a server thread. Properly implement gss_init_sec_context loop for the client part. Still relies on kerberos being used and gss_accept_sec_context beeing finished in one roundtrip.
-rw-r--r--proxy/tests/accept_context.c267
1 files changed, 191 insertions, 76 deletions
diff --git a/proxy/tests/accept_context.c b/proxy/tests/accept_context.c
index efeef09..e493272 100644
--- a/proxy/tests/accept_context.c
+++ b/proxy/tests/accept_context.c
@@ -33,6 +33,7 @@
#include <sys/un.h>
#include <errno.h>
#include <netinet/in.h>
+#include <pthread.h>
#include <gssapi/gssapi.h>
#include "src/gp_utils.h"
#include "src/gp_rpc_process.h"
@@ -69,55 +70,6 @@ done:
return fd;
}
-int client_init_context(char *target, gss_buffer_desc *out_token)
-{
- uint32_t ret_maj;
- uint32_t ret_min;
- gss_buffer_desc target_buf;
- gss_name_t name = GSS_C_NO_NAME;
- gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
- int ret = 0;
-
- target_buf.value = (void *)target;
- target_buf.length = strlen(target) + 1;
-
- ret_maj = gss_import_name(&ret_min, &target_buf,
- GSS_C_NT_HOSTBASED_SERVICE, &name);
- if (ret_maj) {
- goto done;
- }
-
- /* rely on kerberos not requiring more than one pass, so do not loop */
- ret_maj = gss_init_sec_context(&ret_min,
- GSS_C_NO_CREDENTIAL,
- &ctx,
- name,
- GSS_C_NO_OID,
- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
- 0,
- GSS_C_NO_CHANNEL_BINDINGS,
- NULL,
- NULL,
- out_token,
- NULL,
- NULL);
- if (ret_maj != GSS_S_CONTINUE_NEEDED) {
- ret = -1;
- goto done;
- }
- if (!ctx) {
- ret = -1;
- goto done;
- }
-
-done:
- gss_release_name(&ret_min, &name);
- if (ret) {
- return -1;
- }
- return 0;
-}
-
int gp_send_buffer(int fd, char *buf, uint32_t len)
{
uint32_t size;
@@ -159,6 +111,10 @@ int gp_recv_buffer(int fd, char *buf, uint32_t *len)
*len = ntohl(size);
+ if (*len > MAX_RPC_SIZE) {
+ return EINVAL;
+ }
+
pos = 0;
while (*len > pos) {
rn = read(fd, buf + pos, *len - pos);
@@ -177,12 +133,6 @@ int gp_recv_buffer(int fd, char *buf, uint32_t *len)
return 0;
}
-int gp_prep_accept_sec_context(gss_buffer_t in_token,
- gssx_arg_accept_sec_context *args)
-{
- return gp_conv_buffer_to_gssx(in_token, &args->input_token);
-}
-
int gp_send_accept_sec_context(int fd,
gssx_arg_accept_sec_context *arg,
gssx_res_accept_sec_context *res)
@@ -262,6 +212,159 @@ int gp_send_accept_sec_context(int fd,
return 0;
}
+struct athread {
+ pthread_t tid;
+ int *cli_pipe;
+ int *srv_pipe;
+ struct gp_config *cfg;
+ char *target;
+};
+
+void *client_thread(void *pvt)
+{
+ struct athread *data;
+ uint32_t ret_maj;
+ uint32_t ret_min;
+ char buffer[MAX_RPC_SIZE];
+ uint32_t buflen;
+ gss_buffer_desc target_buf;
+ gss_buffer_desc in_token = GSS_C_EMPTY_BUFFER;
+ gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER;
+ gss_name_t name = GSS_C_NO_NAME;
+ gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+ int ret = 0;
+
+ data = (struct athread *)pvt;
+
+ target_buf.value = (void *)data->target;
+ target_buf.length = strlen(data->target) + 1;
+
+ ret_maj = gss_import_name(&ret_min, &target_buf,
+ GSS_C_NT_HOSTBASED_SERVICE, &name);
+ if (ret_maj) {
+ goto done;
+ }
+
+ do {
+ ret_maj = gss_init_sec_context(&ret_min,
+ GSS_C_NO_CREDENTIAL,
+ &ctx,
+ name,
+ GSS_C_NO_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &in_token,
+ NULL,
+ &out_token,
+ NULL,
+ NULL);
+ if (ret_maj == GSS_S_COMPLETE) {
+ break;
+ }
+ if (ret_maj != GSS_S_CONTINUE_NEEDED) {
+ fprintf(stdout,
+ "gss_init_sec_context() failed with: %d\n", ret_maj);
+ goto done;
+ }
+ if (!ctx) {
+ goto done;
+ }
+
+ /* send to server */
+ ret = gp_send_buffer(data->srv_pipe[1],
+ out_token.value, out_token.length);
+ if (ret) {
+ goto done;
+ }
+
+ gss_release_buffer(&ret_min, &out_token);
+
+ /* and wait for reply */
+ ret = gp_recv_buffer(data->cli_pipe[0], buffer, &buflen);
+ if (ret) {
+ goto done;
+ }
+
+ in_token.value = buffer;
+ in_token.length = buflen;
+
+ } while (ret_maj == GSS_S_CONTINUE_NEEDED);
+
+ fprintf(stdout, "client: Success!\n");
+
+done:
+ gss_release_name(&ret_min, &name);
+ gss_release_buffer(&ret_min, &out_token);
+ close(data->cli_pipe[0]);
+ close(data->cli_pipe[1]);
+ pthread_exit(NULL);
+}
+
+void *server_thread(void *pvt)
+{
+ struct athread *data;
+ char buffer[MAX_RPC_SIZE];
+ uint32_t buflen;
+ gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
+ gssx_arg_accept_sec_context arg;
+ gssx_res_accept_sec_context res;
+ int ret;
+ int fd;
+
+ data = (struct athread *)pvt;
+
+ memset(&arg, 0, sizeof(gssx_arg_accept_sec_context));
+ memset(&res, 0, sizeof(gssx_res_accept_sec_context));
+
+ /* connect to the socket first to make sure the proxy is available */
+ fd = connect_unix_socket(data->cfg->socket_name);
+ if (fd == -1) {
+ goto done;
+ }
+
+ ret = gp_recv_buffer(data->srv_pipe[0], buffer, &buflen);
+ if (ret) {
+ fprintf(stdout, "Failed to get data from client!\n");
+ goto done;
+ }
+
+ token.value = buffer;
+ token.length = buflen;
+
+ ret = gp_conv_buffer_to_gssx(&token, &arg.input_token);
+ if (ret) {
+ fprintf(stderr, "gp_conv_buffer_to_gssx() failed!\n");
+ goto done;
+ }
+
+ ret = gp_send_accept_sec_context(fd, &arg, &res);
+ if (ret) {
+ fprintf(stdout, "Comms with gssproxy failed!\n");
+ }
+
+ if (res.status.major_status) {
+ fprintf(stdout, "gssproxy returned an error: %ld\n",
+ res.status.major_status);
+ goto done;
+ }
+
+ gp_conv_gssx_to_buffer(res.output_token, &token);
+
+ ret = gp_send_buffer(data->cli_pipe[1], token.value, token.length);
+ if (ret) {
+ fprintf(stdout, "Failed to send data to client!\n");
+ goto done;
+ }
+
+done:
+ xdr_free((xdrproc_t)xdr_gssx_arg_accept_sec_context, (char *)&arg);
+ xdr_free((xdrproc_t)xdr_gssx_res_accept_sec_context, (char *)&res);
+ close(data->srv_pipe[0]);
+ close(data->srv_pipe[1]);
+ pthread_exit(NULL);
+}
+
int main(int argc, const char *argv[])
{
int opt;
@@ -270,12 +373,13 @@ int main(int argc, const char *argv[])
struct gp_config *cfg;
char *opt_config_file = NULL;
char *opt_target = NULL;
- int fd;
+ int srv_pipe[2];
+ int cli_pipe[2];
+ pthread_attr_t attr;
+ struct athread server;
+ struct athread client;
+ void *retval;
int ret;
- gss_buffer_desc out_token = GSS_C_EMPTY_BUFFER;
- gssx_arg_accept_sec_context arg;
- gssx_res_accept_sec_context res;
- uint32_t ret_min;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -304,42 +408,53 @@ int main(int argc, const char *argv[])
return 0;
}
+ if (opt_target == NULL) {
+ fprintf(stderr, "Missing target!\n");
+ poptPrintUsage(pc, stderr, 0);
+ return 1;
+ }
+
cfg = read_config(opt_config_file, 0);
if (!cfg) {
return -1;
}
- memset(&arg, 0, sizeof(gssx_arg_accept_sec_context));
- memset(&res, 0, sizeof(gssx_res_accept_sec_context));
-
- /* connect to the socket first to make sure the proxy is available */
- fd = connect_unix_socket(cfg->socket_name);
- if (fd == -1) {
+ ret = pipe(srv_pipe);
+ if (ret) {
return -1;
}
-
- ret = client_init_context(opt_target, &out_token);
+ ret = pipe(cli_pipe);
if (ret) {
return -1;
}
- ret = gp_prep_accept_sec_context(&out_token, &arg);
+ /* make thread joinable (portability) */
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ server.srv_pipe = srv_pipe;
+ server.cli_pipe = cli_pipe;
+ server.cfg = cfg;
+ server.target = NULL;
+
+ ret = pthread_create(&server.tid, &attr, server_thread, &server);
if (ret) {
return -1;
}
- ret = gp_send_accept_sec_context(fd, &arg, &res);
+ client.srv_pipe = srv_pipe;
+ client.cli_pipe = cli_pipe;
+ client.cfg = cfg;
+ client.target = opt_target;
+
+ ret = pthread_create(&client.tid, &attr, client_thread, &client);
if (ret) {
return -1;
}
- if (res.status.major_status) {
- return -1;
- }
+ pthread_join(server.tid, &retval);
+ pthread_join(client.tid, &retval);
- xdr_free((xdrproc_t)xdr_gssx_arg_accept_sec_context, (char *)&arg);
- xdr_free((xdrproc_t)xdr_gssx_res_accept_sec_context, (char *)&res);
- gss_release_buffer(&ret_min, &out_token);
return 0;
}