#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
* unsuccessful, the GSS-API error messages are displayed on stderr
* and -1 is returned.
*/
-int client_establish_context(s, service_name, deleg_flag,
+int client_establish_context(s, service_name, deleg_flag, oid,
gss_context, ret_flags)
int s;
char *service_name;
+ gss_OID oid;
OM_uint32 deleg_flag;
gss_ctx_id_t *gss_context;
OM_uint32 *ret_flags;
GSS_C_NO_CREDENTIAL,
gss_context,
target_name,
- GSS_C_NULL_OID,
+ oid,
GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
deleg_flag,
0,
* verifies it with gss_verify. -1 is returned if any step fails,
* otherwise 0 is returned.
*/
-int call_server(host, port, service_name, deleg_flag, msg, use_file)
+int call_server(host, port, oid, service_name, deleg_flag, msg, use_file)
char *host;
u_short port;
+ gss_OID oid;
char *service_name;
OM_uint32 deleg_flag;
char *msg;
return -1;
/* Establish context */
- if (client_establish_context(s, service_name, deleg_flag, &context,
+ if (client_establish_context(s, service_name, deleg_flag, oid, &context,
&ret_flags) < 0) {
(void) close(s);
return -1;
return 0;
}
+static void parse_oid(char *mechanism, gss_OID *oid)
+{
+ char *mechstr = 0, *cp;
+ gss_buffer_desc tok;
+ OM_uint32 maj_stat, min_stat;
+
+ if (isdigit(mechanism[0])) {
+ mechstr = malloc(strlen(mechanism)+5);
+ if (!mechstr) {
+ printf("Couldn't allocate mechanism scratch!\n");
+ return;
+ }
+ sprintf(mechstr, "{ %s }", mechanism);
+ for (cp = mechstr; *cp; cp++)
+ if (*cp == '.')
+ *cp = ' ';
+ tok.value = mechstr;
+ } else
+ tok.value = mechanism;
+ tok.length = strlen(tok.value);
+ maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("str_to_oid", maj_stat, min_stat);
+ return;
+ }
+ if (mechstr)
+ free(mechstr);
+}
+
int main(argc, argv)
int argc;
char **argv;
{
char *service_name, *server_host, *msg;
+ char *mechanism = 0;
u_short port = 4444;
int use_file = 0;
- OM_uint32 deleg_flag = 0;
+ OM_uint32 deleg_flag = 0, min_stat;
+ gss_OID oid = GSS_C_NULL_OID;
display_file = stdout;
argc--; argv++;
if (!argc) usage();
port = atoi(*argv);
- } else if (strcmp(*argv, "-d") == 0) {
+ } else if (strcmp(*argv, "-mech") == 0) {
+ argc--; argv++;
+ if (!argc) usage();
+ mechanism = *argv;
+ } else if (strcmp(*argv, "-d") == 0) {
deleg_flag = GSS_C_DELEG_FLAG;
} else if (strcmp(*argv, "-f") == 0) {
use_file = 1;
service_name = *argv++;
msg = *argv++;
- if (call_server(server_host, port, service_name,
+ if (mechanism)
+ parse_oid(mechanism, &oid);
+
+ if (call_server(server_host, port, oid, service_name,
deleg_flag, msg, use_file) < 0)
exit(1);
+ if (oid != GSS_C_NULL_OID)
+ (void) gss_release_oid(&min_stat, &oid);
+
return 0;
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <netinet/in.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <strings.h>
#endif
-usage()
+void usage()
{
fprintf(stderr, "Usage: gss-server [-port port] [-verbose]\n");
fprintf(stderr, " [-inetd] [-logfile file] [service_name]\n");
gss_name_t client;
gss_OID doid;
OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc oid_name;
*context = GSS_C_NO_CONTEXT;
return -1;
if (verbose && log) {
- fprintf(log, "Received token: \n");
+ fprintf(log, "Received token (size=%d): \n", recv_tok.length);
print_token(&recv_tok);
}
if (send_tok.length != 0) {
if (verbose && log) {
fprintf(log,
- "Sending accept_sec_context token (size=%d)...",
+ "Sending accept_sec_context token (size=%d):\n",
send_tok.length);
print_token(&send_tok);
}
(void) gss_release_buffer(&min_stat, &send_tok);
}
- if (log) {
+ if (verbose && log) {
if (maj_stat == GSS_S_CONTINUE_NEEDED)
- fprintf(log, "\n");
- else
fprintf(log, "continue needed...\n");
+ else
+ fprintf(log, "\n");
fflush(log);
}
} while (maj_stat == GSS_S_CONTINUE_NEEDED);
/* display the flags */
display_ctx_flags(*ret_flags);
+ if (verbose && log) {
+ maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("converting oid->string", maj_stat, min_stat);
+ return -1;
+ }
+ fprintf(log, "Accepted connection using mechanism OID %.*s.\n",
+ (int) oid_name.length, (char *) oid_name.value);
+ (void) gss_release_buffer(&min_stat, &oid_name);
+ }
+
maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
if (maj_stat != GSS_S_COMPLETE) {
display_status("displaying name", maj_stat, min_stat);
return s;
}
+static float timeval_subtract(tv1, tv2)
+ struct timeval *tv1, *tv2;
+{
+ return ((tv1->tv_sec - tv2->tv_sec) +
+ ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
+}
+
+/*
+ * Yes, yes, this isn't the best place for doing this test.
+ * DO NOT REMOVE THIS UNTIL A BETTER TEST HAS BEEN WRITTEN, THOUGH.
+ * -TYT
+ */
+int test_import_export_context(context)
+ gss_ctx_id_t *context;
+{
+ OM_uint32 min_stat, maj_stat;
+ gss_buffer_desc context_token, copied_token;
+ struct timeval tm1, tm2;
+
+ /*
+ * Attempt to save and then restore the context.
+ */
+ gettimeofday(&tm1, (struct timezone *)0);
+ maj_stat = gss_export_sec_context(&min_stat, context, &context_token);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("exporting context", maj_stat, min_stat);
+ return 1;
+ }
+ gettimeofday(&tm2, (struct timezone *)0);
+ if (verbose && log)
+ fprintf(log, "Exported context: %d bytes, %7.4f seconds\n",
+ context_token.length, timeval_subtract(&tm2, &tm1));
+ copied_token.length = context_token.length;
+ copied_token.value = malloc(context_token.length);
+ if (copied_token.value == 0) {
+ fprintf(log, "Couldn't allocate memory to copy context token.\n");
+ return 1;
+ }
+ memcpy(copied_token.value, context_token.value, copied_token.length);
+ maj_stat = gss_import_sec_context(&min_stat, &copied_token, context);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("importing context", maj_stat, min_stat);
+ return 1;
+ }
+ gettimeofday(&tm1, (struct timezone *)0);
+ if (verbose && log)
+ fprintf(log, "Importing context: %7.4f seconds\n",
+ timeval_subtract(&tm1, &tm2));
+ (void) gss_release_buffer(&min_stat, &context_token);
+ return 0;
+}
+
/*
* Function: sign_server
*
return(-1);
printf("Accepted connection: \"%.*s\"\n",
- client_name.length, client_name.value);
+ (int) client_name.length, (char *) client_name.value);
(void) gss_release_buffer(&min_stat, &client_name);
+ for (i=0; i < 3; i++)
+ if (test_import_export_context(&context))
+ return -1;
+
/* Receive the sealed message token */
if (recv_token(s, &xmit_buf) < 0)
return(-1);
} else {
int stmp;
- if (stmp = create_socket(port)) {
+ if ((stmp = create_socket(port))) {
do {
/* Accept a TCP connection */
if ((s = accept(stmp, NULL, 0)) < 0) {