+Sat Mar 2 03:03:27 1996 Theodore Y. Ts'o <tytso@dcl>
+
+ * gss-server.c (sign_server): Do better import/export security
+ checking. If the received message to be signed is not
+ printable (at least the first two characters are not),
+ display the message in hex. Print the hex values of the
+ incoming and outcoming packets, for your information.
+
+ * gss-misc.c (print_token, display_buffer): Two new tokens for
+ displaying GSSAPI buffers, either has hex or as a
+ printable string.
+
+ * gss-client.c (call_server): Add option to support reading in the
+ message to be signed from a file.
+
Wed Feb 28 11:42:26 1996 Theodore Y. Ts'o <tytso@dcl>
* gss-client.c (call_server): Get the nametype OID from
*/
#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_generic.h>
int establish_context();
int connect_to_server();
int call_server();
+int client_establish_context();
int send_token();
int recv_token();
+void read_file();
int deleg_flag;
void display_status();
extern FILE *display_file;
-usage()
+
+void usage()
{
fprintf(stderr, "Usage: gss-client [-port port] [-d] [-v2] host service \
msg\n");
exit(1);
}
-main(argc, argv)
+int main(argc, argv)
int argc;
char **argv;
{
char *service_name, *server_host, *msg;
u_short port = 4444;
int v2 = 0;
+ int use_file = 0;
display_file = stdout;
deleg_flag = 0;
v2 = 1;
} else if (strcmp(*argv, "-d") == 0) {
deleg_flag = GSS_C_DELEG_FLAG;
+ } else if (strcmp(*argv, "-f") == 0) {
+ use_file = 1;
} else
break;
argc--; argv++;
service_name = *argv++;
msg = *argv++;
- if (call_server(server_host, port, v2, service_name, msg) < 0)
+ if (call_server(server_host, port, v2, service_name, msg, use_file) < 0)
exit(1);
return 0;
* verifies it with gss_verify. -1 is returned if any step fails,
* otherwise 0 is returned.
*/
-int call_server(host, port, dov2, service_name, msg)
+int call_server(host, port, dov2, service_name, msg, use_file)
char *host;
u_short port;
int dov2;
char *service_name;
char *msg;
+ int use_file;
{
gss_ctx_id_t context;
gss_buffer_desc in_buf, out_buf, context_token;
#else /* GSSAPI_V2 */
int context_flags;
#endif /* GSSAPI_V2 */
-
/* Open connection */
if ((s = connect_to_server(host, port)) < 0)
return -1;
}
fprintf(stderr, "\"%s\" to \"%s\", lifetime %d, flags %x, %s",
- sname.value, tname.value, lifetime, context_flags,
+ (char *) sname.value, (char *) tname.value, lifetime,
+ context_flags,
(is_local) ? "locally initiated" : "remotely initiated");
#ifdef GSSAPI_V2
fprintf(stderr, " %s", (is_open) ? "open" : "closed");
return -1;
}
fprintf(stderr, "Name type of source name is %s.\n",
- oid_name.value);
+ (char *) oid_name.value);
(void) gss_release_buffer(&min_stat, &oid_name);
(void) gss_release_oid(&min_stat, &name_type);
return -1;
}
fprintf(stderr, "Mechanism %s supports %d names\n",
- oid_name.value, mech_names->count);
+ (char *) oid_name.value, mech_names->count);
(void) gss_release_buffer(&min_stat, &oid_name);
for (i=0; i<mech_names->count; i++) {
gss_OID tmpoid;
display_status("converting oid->string", maj_stat, min_stat);
return -1;
}
- fprintf(stderr, "%d: %s\n", i, oid_name.value);
+ fprintf(stderr, "%d: %s\n", i, (char *) oid_name.value);
maj_stat = gss_str_to_oid(&min_stat,
&oid_name,
}
if (!is_present) {
fprintf(stderr, "%s is not present in list?\n",
- oid_name.value);
+ (char *) oid_name.value);
}
(void) gss_release_oid(&min_stat, &tmpoid);
(void) gss_release_buffer(&min_stat, &oid_name);
}
#endif /* GSSAPI_V2 */
- /* Seal the message */
- in_buf.value = msg;
- in_buf.length = strlen(msg) + 1;
+ if (use_file) {
+ read_file(msg, &in_buf);
+ } else {
+ /* Seal the message */
+ in_buf.value = msg;
+ in_buf.length = strlen(msg) + 1;
+ }
#ifdef GSSAPI_V2
if (dov2)
maj_stat = gss_wrap(&min_stat, context, 1, GSS_C_QOP_DEFAULT,
} else if (! state) {
fprintf(stderr, "Warning! Message not encrypted.\n");
}
+ if (use_file)
+ free(in_buf.value);
/* Send to server */
if (send_token(s, &out_buf) < 0)
}
if (send_tok.length != 0) {
+ printf("Sending init_sec_context token (size=%d)...",
+ send_tok.length);
if (send_token(s, &send_tok) < 0) {
(void) gss_release_buffer(&min_stat, &send_tok);
(void) gss_release_name(&min_stat, &target_name);
(void) gss_release_buffer(&min_stat, &send_tok);
if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+ printf("continue needed...");
if (recv_token(s, &recv_tok) < 0) {
(void) gss_release_name(&min_stat, &target_name);
return -1;
}
token_ptr = &recv_tok;
}
+ printf("\n");
} while (maj_stat == GSS_S_CONTINUE_NEEDED);
(void) gss_release_name(&min_stat, &target_name);
return 0;
}
+
+
+void read_file(file_name, in_buf)
+ char *file_name;
+ gss_buffer_t in_buf;
+{
+ int fd, bytes_in, count;
+ struct stat stat_buf;
+
+ if ((fd = open(file_name, O_RDONLY, 0)) < 0) {
+ perror("open");
+ fprintf(stderr, "Couldn't open file %s\n", file_name);
+ exit(1);
+ }
+ if (fstat(fd, &stat_buf) < 0) {
+ perror("fstat");
+ exit(1);
+ }
+ in_buf->length = stat_buf.st_size;
+ in_buf->value = malloc(in_buf->length);
+ if (in_buf->value == 0) {
+ fprintf(stderr, "Couldn't allocate %d byte buffer for reading file\n",
+ in_buf->length);
+ exit(1);
+ }
+ memset(in_buf->value, 0, in_buf->length);
+ for (bytes_in = 0; bytes_in < in_buf->length; bytes_in += count) {
+ count = read(fd, in_buf->value, in_buf->length);
+ if (count < 0) {
+ perror("read");
+ exit(1);
+ }
+ if (count == 0)
+ break;
+ }
+ if (bytes_in != count)
+ fprintf(stderr, "Warning, only read in %d bytes, expected %d\n",
+ bytes_in, count);
+}
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <string.h>
#include <gssapi/gssapi.h>
#include <gssapi/gssapi_generic.h>
break;
}
}
+
+void print_token(tok)
+ gss_buffer_t tok;
+{
+ int i;
+ unsigned char *p = tok->value;
+
+ if (!display_file)
+ return;
+ for (i=0; i < tok->length; i++, p++) {
+ fprintf(display_file, "%02x ", *p);
+ if ((i % 16) == 15) {
+ fprintf(display_file, "\n");
+ }
+ }
+ fprintf(display_file, "\n");
+ fflush(display_file);
+}
+
+void display_buffer(buffer)
+ gss_buffer_desc buffer;
+{
+ char *namebuf;
+
+ if (!display_file)
+ return;
+ namebuf = malloc(buffer.length+1);
+ if (!namebuf) {
+ fprintf(stderr, "display_buffer: couldn't allocate buffer!\n");
+ exit(1);
+ }
+ strncpy(namebuf, buffer.value, buffer.length);
+ namebuf[buffer.length] = '\0';
+ fprintf(display_file, "%s", namebuf);
+ free(namebuf);
+}
+
+
+
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <stdlib.h>
+#include <ctype.h>
#include <sys/time.h>
#include <time.h>
int send_token();
int recv_token();
void display_status();
+int test_import_export_context();
+void print_token();
+
+int server_acquire_creds();
+int server_establish_context();
+int sign_server();
extern FILE *display_file;
FILE *log;
+int verbose = 0;
void
usage()
} else if (strcmp(*argv, "-inetd") == 0) {
do_inetd = 1;
display_file = 0;
+ } else if (strcmp(*argv, "-verbose") == 0) {
+ verbose = 1;
} else if (strcmp(*argv, "-v2") == 0) {
dov2 = 1;
} else if (strcmp(*argv, "-once") == 0) {
int once;
{
gss_cred_id_t server_creds;
- gss_buffer_desc client_name, xmit_buf, msg_buf, context_token;
+ gss_buffer_desc client_name, xmit_buf, msg_buf;
gss_ctx_id_t context;
OM_uint32 maj_stat, min_stat;
- int s2;
+ int i,s2;
time_t now;
+ char *cp;
if (server_acquire_creds(service_name, &server_creds) < 0)
return -1;
(void) gss_release_buffer(&min_stat, &client_name);
if (dov2) {
- /*
- * Attempt to save and then restore the context.
- */
- 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);
- break;
- }
- fprintf(log, "Exported context: %d bytes\n", context_token.length);
- maj_stat = gss_import_sec_context(&min_stat,
- &context_token,
- &context);
- if (maj_stat != GSS_S_COMPLETE) {
- display_status("importing context", maj_stat, min_stat);
- break;
- }
- (void) gss_release_buffer(&min_stat, &context_token);
+ for (i=0; i < 3; i++)
+ if (test_import_export_context(&context))
+ break;
+ if (i < 3)
+ break;
}
/* Receive the sealed message token */
if (recv_token(s2, &xmit_buf) < 0)
break;
+
+ if (verbose && log) {
+ fprintf(log, "Sealed message token:\n");
+ print_token(xmit_buf);
+ }
#ifdef GSSAPI_V2
if (dov2)
(void) gss_release_buffer(&min_stat, &xmit_buf);
- fprintf(log, "Received message: \"%s\"\n", (char *) msg_buf.value);
-
+ fprintf(log, "Received message: ");
+ cp = msg_buf.value;
+ if (isprint(cp[0]) && isprint(cp[1]))
+ fprintf(log, "\"%s\"\n", cp);
+ else {
+ printf("\n");
+ print_token(msg_buf);
+ }
+
/* Produce a signature block for the message */
#ifdef GSSAPI_V2
if (dov2)
if (recv_token(s, &recv_tok) < 0)
return -1;
+ if (verbose && log) {
+ fprintf(log, "Received token: \n");
+ print_token(&recv_tok);
+ }
+
maj_stat =
gss_accept_sec_context(&min_stat,
context,
}
(void) gss_release_buffer(&min_stat, &recv_tok);
-
if (send_tok.length != 0) {
+ if (verbose && log) {
+ fprintf(log,
+ "Sending accept_sec_context token (size=%d)...",
+ send_tok.length);
+ print_token(&send_tok);
+ }
if (send_token(s, &send_tok) < 0) {
fprintf(log, "failure sending token\n");
return -1;
(void) gss_release_buffer(&min_stat, &send_tok);
}
+ if (maj_stat == GSS_S_CONTINUE_NEEDED)
+ if (log)
+ fprintf(log, "continue needed...");
+ if (log) {
+ fprintf(log, "\n");
+ fflush(log);
+ }
} while (maj_stat == GSS_S_CONTINUE_NEEDED);
maj_stat = gss_display_name(&min_stat, client, client_name, &doid);
return 0;
}
-
+static float timeval_subtract(struct timeval *tv1,
+ struct timeval *tv2)
+{
+ return ((tv1->tv_sec - tv2->tv_sec) +
+ ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
+}
+int test_import_export_context(context)
+ gss_ctx_id_t *context;
+{
+ OM_uint32 min_stat, maj_stat;
+ gss_buffer_desc context_token;
+ struct timeval tm1, tm2;
+
+ /*
+ * Attempt to save and then restore the context.
+ */
+ gettimeofday(&tm1);
+ 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);
+ if (verbose && log)
+ fprintf(log, "Exported context: %d bytes, %7.4f seconds\n",
+ context_token.length, timeval_subtract(&tm2, &tm1));
+ maj_stat = gss_import_sec_context(&min_stat, &context_token, context);
+ if (maj_stat != GSS_S_COMPLETE) {
+ display_status("importing context", maj_stat, min_stat);
+ return 1;
+ }
+ gettimeofday(&tm1);
+ 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;
+}