gss sample program
authorKeith Vetter <keithv@fusion.com>
Fri, 29 Sep 1995 02:01:22 +0000 (02:01 +0000)
committerKeith Vetter <keithv@fusion.com>
Fri, 29 Sep 1995 02:01:22 +0000 (02:01 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@6880 dc483132-0cff-0310-8789-dd5450dbe970

src/mac/gss-sample/ChangeLog [new file with mode: 0644]
src/mac/gss-sample/gss-client.c [new file with mode: 0644]
src/mac/gss-sample/gss-misc.c [new file with mode: 0644]
src/mac/gss-sample/gss-sample.sit.hqx [new file with mode: 0644]
src/mac/gss-sample/gss.h [new file with mode: 0644]

diff --git a/src/mac/gss-sample/ChangeLog b/src/mac/gss-sample/ChangeLog
new file mode 100644 (file)
index 0000000..63f0612
--- /dev/null
@@ -0,0 +1,3 @@
+Thu 26 12:00:00 1995  John Rivlin <jrivlin@fusion.com>
+
+       * Created GSS Sample program
diff --git a/src/mac/gss-sample/gss-client.c b/src/mac/gss-sample/gss-client.c
new file mode 100644 (file)
index 0000000..d7dd26e
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ * Copyright 1994 by OpenVision Technologies, Inc.
+ * 
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ * 
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define GSSAPI_V2
+
+#include "gss.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+usage()
+{
+     fprintf(stderr, "Usage: gss-client [-port port] [-v2] host service msg\r");
+     exit(1);
+}
+
+int main(argc, argv)
+     int argc;
+     char **argv;
+{
+     char *service_name, *server_host, *msg;
+     u_short port = 4444;
+     int v2 = 0;
+     
+     argc = ccommand(&argv);
+     
+     /* Parse arguments. */
+     argc--; argv++;
+     while (argc) {
+         if (strcmp(*argv, "-port") == 0) {
+              argc--; argv++;
+              if (!argc) usage();
+              port = atoi(*argv);
+         } else if (strcmp(*argv, "-v2") == 0) {
+              v2 = 1;
+         } else 
+              break;
+         argc--; argv++;
+     }
+     if (argc != 3)
+         usage();
+
+     server_host = *argv++;
+     service_name = *argv++;
+     msg = *argv++;
+
+     if (call_server(server_host, port, v2, service_name, msg) < 0)
+         exit(1);
+
+     return 0;
+}
+
+/*
+ * Function: call_server
+ *
+ * Purpose: Call the "sign" service.
+ *
+ * Arguments:
+ *
+ *     host            (r) the host providing the service
+ *     port            (r) the port to connect to on host
+ *     service_name    (r) the GSS-API service name to authenticate to 
+ *     msg             (r) the message to have "signed"
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * call_server opens a TCP connection to <host:port> and establishes a
+ * GSS-API context with service_name over the connection.  It then
+ * seals msg in a GSS-API token with gss_seal, sends it to the server,
+ * reads back a GSS-API signature block for msg from the server, and
+ * verifies it with gss_verify.  -1 is returned if any step fails,
+ * otherwise 0 is returned.
+ */
+int call_server(char *host, u_short port, int dov2, char *service_name, char *msg)
+{
+     gss_ctx_id_t context;
+     gss_buffer_desc in_buf, out_buf, context_token;
+     int state;
+     SOCKET s;
+     OM_uint32 maj_stat, min_stat;
+     gss_name_t        src_name, targ_name;
+     gss_buffer_desc sname, tname;
+     OM_uint32 lifetime;
+     gss_OID mechanism;
+     int is_local;
+#ifdef GSSAPI_V2
+     OM_uint32 context_flags;
+     int is_open;
+     gss_qop_t qop_state;
+     gss_OID_set mech_names;
+     gss_buffer_desc oid_name;
+#else  /* GSSAPI_V2 */
+     int context_flags;
+#endif /* GSSAPI_V2 */
+     
+
+     /* Open connection */
+     if ((s = connect_to_server(host, port)) == (SOCKET) -1)
+         return -1;
+
+     /* Establish context */
+     if (client_establish_context(s, service_name, &context) < 0)
+         return -1;
+
+#ifdef GSSAPI_V2
+     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);
+            return -1;
+        }
+        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;
+        }
+        (void) gss_release_buffer(&min_stat, &context_token);
+     }
+#endif /* GSSAPI_V2 */
+
+     /* Get context information */
+     maj_stat = gss_inquire_context(&min_stat, context,
+                                   &src_name, &targ_name, &lifetime,
+                                   &mechanism, &context_flags,
+                                   &is_local
+#ifdef GSSAPI_V2
+                                   , &is_open
+#endif /* GSSAPI_V2 */
+                                   );
+     if (maj_stat != GSS_S_COMPLETE) {
+        display_status("inquiring context", maj_stat, min_stat);
+        return -1;
+     }
+
+     maj_stat = gss_display_name(&min_stat, src_name, &sname,
+                                (gss_OID *) NULL);
+     if (maj_stat != GSS_S_COMPLETE) {
+        display_status("displaying context", maj_stat, min_stat);
+        return -1;
+     }
+     maj_stat = gss_display_name(&min_stat, targ_name, &tname,
+                                (gss_OID *) NULL);
+     if (maj_stat != GSS_S_COMPLETE) {
+        display_status("displaying context", maj_stat, min_stat);
+        return -1;
+     }
+     fprintf(stderr, "\"%s\" to \"%s\"\r   lifetime %d, flags %x, %s",
+            sname.value, tname.value, lifetime, context_flags,
+            (is_local) ? "locally initiated" : "remotely initiated");
+#ifdef GSSAPI_V2
+     fprintf(stderr, " %s", (is_open) ? "open" : "closed");
+#endif /* GSSAPI_V2 */
+     fprintf(stderr, "\r");
+
+     (void) gss_release_name(&min_stat, &src_name);
+     (void) gss_release_name(&min_stat, &targ_name);
+     (void) gss_release_buffer(&min_stat, &sname);
+     (void) gss_release_buffer(&min_stat, &tname);
+
+#ifdef GSSAPI_V2
+     if (dov2) {
+        size_t i;
+
+        /* Now get the names supported by the mechanism */
+        maj_stat = gss_inquire_names_for_mech(&min_stat,
+                                              mechanism,
+                                              &mech_names);
+        if (maj_stat != GSS_S_COMPLETE) {
+            display_status("inquiring mech names", maj_stat, min_stat);
+            return -1;
+        }
+
+        maj_stat = gss_oid_to_str(&min_stat,
+                                  mechanism,
+                                  &oid_name);
+        if (maj_stat != GSS_S_COMPLETE) {
+            display_status("converting oid->string", maj_stat, min_stat);
+            return -1;
+        }
+        fprintf(stderr, "Mechanism %s supports %d names\r",
+                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;
+            int        is_present;
+
+            maj_stat = gss_oid_to_str(&min_stat,
+                                      &mech_names->elements[i],
+                                      &oid_name);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("converting oid->string", maj_stat, min_stat);
+                return -1;
+            }
+            fprintf(stderr, "%d: %s\r", i, oid_name.value);
+
+            maj_stat = gss_str_to_oid(&min_stat,
+                                      &oid_name,
+                                      &tmpoid);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("converting string->oid", maj_stat, min_stat);
+                return -1;
+            }
+
+            maj_stat = gss_test_oid_set_member(&min_stat,
+                                               tmpoid,
+                                               mech_names,
+                                               &is_present);
+            if (maj_stat != GSS_S_COMPLETE) {
+                display_status("testing oid presence", maj_stat, min_stat);
+                return -1;
+            }
+            if (!is_present) {
+                fprintf(stderr, "%s is not present in list?\r",
+                        oid_name.value);
+            }
+            (void) gss_release_oid(&min_stat, &tmpoid);
+            (void) gss_release_buffer(&min_stat, &oid_name);
+        }
+
+        (void) gss_release_oid_set(&min_stat, &mech_names);
+        (void) gss_release_oid(&min_stat, &mechanism);
+     }
+#endif /* GSSAPI_V2 */
+
+     /* 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,
+                            &in_buf, &state, &out_buf);
+     else
+#endif /* GSSAPI_V2 */
+     maj_stat = gss_seal(&min_stat, context, 1, GSS_C_QOP_DEFAULT,
+                        &in_buf, &state, &out_buf);
+     if (maj_stat != GSS_S_COMPLETE) {
+         display_status("sealing message", maj_stat, min_stat);
+         return -1;
+     } else if (! state) {
+         fprintf(stderr, "Warning!  Message not encrypted.\r");
+     }
+
+     /* Send to server */
+     if (send_token(s, &out_buf) < 0)
+         return -1;
+     (void) gss_release_buffer(&min_stat, &out_buf);
+
+     /* Read signature block into out_buf */
+     if (recv_token(s, &out_buf) < 0)
+         return -1;
+
+     /* Verify signature block */
+#ifdef GSSAPI_V2
+     if (dov2)
+        maj_stat = gss_verify_mic(&min_stat, context, &in_buf,
+                                  &out_buf, &qop_state);
+     else
+#endif /* GSSAPI_V2 */
+     maj_stat = gss_verify(&min_stat, context, &in_buf, &out_buf, &state);
+     if (maj_stat != GSS_S_COMPLETE) {
+         display_status("verifying signature", maj_stat, min_stat);
+         return -1;
+     }
+     (void) gss_release_buffer(&min_stat, &out_buf);
+
+     printf("Signature verified.\r");
+
+     /* Delete context */
+     maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf);
+     if (maj_stat != GSS_S_COMPLETE) {
+         display_status("deleting context", maj_stat, min_stat);
+         return -1;
+     }
+     (void) gss_release_buffer(&min_stat, &out_buf);
+     
+     closesocket(s);
+     
+     return 0;
+}
+
+/*
+ * Function: connect_to_server
+ *
+ * Purpose: Opens a TCP connection to the name host and port.
+ *
+ * Arguments:
+ *
+ *     host            (r) the target host name
+ *     port            (r) the target port, in host byte order
+ *
+ * Returns: the established socket file desciptor, or -1 on failure
+ *
+ * Effects:
+ *
+ * The host name is resolved with gethostbyname(), and the socket is
+ * opened and connected.  If an error occurs, an error message is
+ * displayed and -1 is returned.
+ */
+SOCKET connect_to_server(char *host, u_short port)
+{
+     struct sockaddr_in saddr;
+     struct hostent *hp;
+     SOCKET s;
+     
+     if ((hp = gethostbyname(host)) == NULL) {
+         fprintf(stderr, "Unknown host: %s\r", host);
+         return (SOCKET) -1;
+     }
+     
+     saddr.sin_family = hp->h_addrtype;
+     memcpy((char *)&saddr.sin_addr, hp->h_addr, hp->h_length);
+     saddr.sin_port = htons(port);
+
+     if ((s = socket(AF_INET, SOCK_STREAM, 0)) == (SOCKET) -1) {
+         perror("creating socket");
+         return (SOCKET) -1;
+     }
+     if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
+         perror("connecting to server");
+         return (SOCKET) -1;
+     }
+     return s;
+}
+
+
+/*
+ * Function: client_establish_context
+ *
+ * Purpose: establishes a GSS-API context with a specified service and
+ * returns the context handle
+ *
+ * Arguments:
+ *
+ *     s               (r) an established TCP connection to the service
+ *     service_name    (r) the ASCII service name of the service
+ *     context         (w) the established GSS-API context
+ *
+ * Returns: 0 on success, -1 on failure
+ *
+ * Effects:
+ * 
+ * service_name is imported as a GSS-API name and a GSS-API context is
+ * established with the corresponding service; the service should be
+ * listening on the TCP connection s.  The default GSS-API mechanism
+ * is used, and mutual authentication and replay detection are
+ * requested.
+ * 
+ * If successful, the context handle is returned in context.  If
+ * unsuccessful, the GSS-API error messages are displayed on stderr
+ * and -1 is returned.
+ */
+int client_establish_context(SOCKET s, char *service_name, gss_ctx_id_t *gss_context)
+{
+     gss_buffer_desc send_tok, recv_tok, *token_ptr;
+     gss_name_t target_name;
+     OM_uint32 maj_stat, min_stat;
+
+     /*
+      * Import the name into target_name.  Use send_tok to save
+      * local variable space.
+      */
+     send_tok.value = service_name;
+     send_tok.length = strlen(service_name) + 1;
+     maj_stat = gss_import_name(&min_stat, &send_tok,
+                               (gss_OID) gss_nt_service_name, &target_name);
+     if (maj_stat != GSS_S_COMPLETE) {
+         display_status("parsing name", maj_stat, min_stat);
+         return -1;
+     }
+     
+     /*
+      * Perform the context-establishement loop.
+      *
+      * On each pass through the loop, token_ptr points to the token
+      * to send to the server (or GSS_C_NO_BUFFER on the first pass).
+      * Every generated token is stored in send_tok which is then
+      * transmitted to the server; every received token is stored in
+      * recv_tok, which token_ptr is then set to, to be processed by
+      * the next call to gss_init_sec_context.
+      * 
+      * GSS-API guarantees that send_tok's length will be non-zero
+      * if and only if the server is expecting another token from us,
+      * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
+      * and only if the server has another token to send us.
+      */
+     
+     token_ptr = GSS_C_NO_BUFFER;
+     *gss_context = GSS_C_NO_CONTEXT;
+
+     do {
+         maj_stat =
+              gss_init_sec_context(&min_stat,
+                                   GSS_C_NO_CREDENTIAL,
+                                   gss_context,
+                                   target_name,
+                                   GSS_C_NULL_OID,
+                                   GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+                                   0,
+                                   NULL,       /* no channel bindings */
+                                   token_ptr,
+                                   NULL,       /* ignore mech type */
+                                   &send_tok,
+                                   NULL,       /* ignore ret_flags */
+                                   NULL);      /* ignore time_rec */
+
+         if (token_ptr != GSS_C_NO_BUFFER)
+              (void) gss_release_buffer(&min_stat, &recv_tok);
+
+         if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
+              display_status("initializing context", maj_stat, min_stat);
+              (void) gss_release_name(&min_stat, &target_name);
+              return -1;
+         }
+
+         if (send_tok.length != 0) {
+              if (send_token(s, &send_tok) < 0) {
+                   (void) gss_release_buffer(&min_stat, &send_tok);
+                   (void) gss_release_name(&min_stat, &target_name);
+                   return -1;
+              }
+         }
+         (void) gss_release_buffer(&min_stat, &send_tok);
+         
+         if (maj_stat == GSS_S_CONTINUE_NEEDED) {
+              if (recv_token(s, &recv_tok) < 0) {
+                   (void) gss_release_name(&min_stat, &target_name);
+                   return -1;
+              }
+              token_ptr = &recv_tok;
+         }
+     } while (maj_stat == GSS_S_CONTINUE_NEEDED);
+
+     (void) gss_release_name(&min_stat, &target_name);
+     return 0;
+}
diff --git a/src/mac/gss-sample/gss-misc.c b/src/mac/gss-sample/gss-misc.c
new file mode 100644 (file)
index 0000000..b47cf89
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+
+ * Copyright 1994 by OpenVision Technologies, Inc.
+
+ * 
+
+ * Permission to use, copy, modify, distribute, and sell this software
+
+ * and its documentation for any purpose is hereby granted without fee,
+
+ * provided that the above copyright notice appears in all copies and
+
+ * that both that copyright notice and this permission notice appear in
+
+ * supporting documentation, and that the name of OpenVision not be used
+
+ * in advertising or publicity pertaining to distribution of the software
+
+ * without specific, written prior permission. OpenVision makes no
+
+ * representations about the suitability of this software for any
+
+ * purpose.  It is provided "as is" without express or implied warranty.
+
+ * 
+
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+
+ * PERFORMANCE OF THIS SOFTWARE.
+
+ */
+
+
+
+#include "gss.h"
+
+#include <string.h>
+
+#include <errno.h>
+
+#include <stdio.h>
+
+#include <stdlib.h>
+
+
+
+/*
+
+ * Function: send_token
+
+ *
+
+ * Purpose: Writes a token to a file descriptor.
+
+ *
+
+ * Arguments:
+
+ *
+
+ *     s               (r) an open file descriptor
+
+ *     tok             (r) the token to write
+
+ *
+
+ * Returns: 0 on success, -1 on failure
+
+ *
+
+ * Effects:
+
+ *
+
+ * send_token writes the token length (as a network long) and then the
+
+ * token data to the file descriptor s.         It returns 0 on success, and
+
+ * -1 if an error occurs or if it could not write all the data.
+
+ */
+
+int send_token(SOCKET s, gss_buffer_t tok) {
+
+    size_t ret;
+
+
+
+    ret = send(s, (char *) &tok->length, 4, 0);
+
+
+
+       if (ret < 0) {
+
+               fprintf(stderr, "Error sending token length\r");
+
+               return -1;
+
+       }
+
+       else if (ret != 4) {
+
+               fprintf(stderr, "sending token length: %d of %d bytes written\r", ret, 4);
+
+               return -1;
+
+       }
+
+
+
+    ret = send(s, tok->value, tok->length, 0);
+
+
+
+       if (ret < 0) {
+
+               fprintf(stderr, "Error sending data\r");
+
+               return -1;
+
+       }
+
+       else if (ret != tok->length) {
+
+               fprintf(stderr, "sending token data: %d of %d bytes written\r", ret, tok->length);
+
+               return -1;
+
+       }
+
+
+
+    return 0;
+
+
+
+} /* send_token */
+
+
+
+
+
+/*
+
+ * Function: recv_token
+
+ *
+
+ * Purpose: Reads a token from a file descriptor.
+
+ *
+
+ * Arguments:
+
+ *
+
+ *     s               (r) an open file descriptor
+
+ *     tok             (w) the read token
+
+ *
+
+ * Returns: 0 on success, -1 on failure
+
+ *
+
+ * Effects:
+
+ * 
+
+ * recv_token reads the token length (as a network long), allocates
+
+ * memory to hold the data, and then reads the token data from the
+
+ * file descriptor s.  It blocks to read the length and data, if
+
+ * necessary.  On a successful return, the token should be freed with
+
+ * gss_release_buffer. It returns 0 on success, and -1 if an error
+
+ * occurs or if it could not read all the data.
+
+ */
+
+int
+
+recv_token (SOCKET s, gss_buffer_t tok) {
+
+    int ret;
+
+    unsigned long len;
+
+
+
+    ret = recv(s, (char *) &len, 4, 0);
+
+
+
+    if (ret < 0) {
+
+               fprintf(stderr, "Error reading token length\r");
+
+           return -1;
+
+     } 
+
+     else if (ret != 4) {
+
+            fprintf(stderr, "Error reading token length: %d of %d bytes read\r", ret, 4);
+
+            return -1;
+
+     }
+
+
+
+    tok->length = (size_t) len;
+
+
+
+    tok->value = (char *) malloc(tok->length);
+
+
+
+    if (tok->value == NULL) {
+
+        fprintf(stderr, "Out of memory allocating token data\r");
+
+        return -1;
+
+     }
+
+
+
+    ret = recv (s, (char *) tok->value, tok->length, 0);
+
+
+
+    if (ret < 0) {
+
+            fprintf(stderr, "Error reading token data\r");
+
+            free(tok->value);
+
+            return -1;
+
+    }
+
+
+
+    return 0;
+
+} /* recv_token */
+
+
+
+
+
+/*
+
+ * Function: display_status
+
+ *
+
+ * Purpose: displays GSS-API messages
+
+ *
+
+ * Arguments:
+
+ *
+
+ *     msg             a string to be displayed with the message
+
+ *     maj_stat        the GSS-API major status code
+
+ *     min_stat        the GSS-API minor status code
+
+ *
+
+ * Effects:
+
+ *
+
+ * The GSS-API messages associated with maj_stat and min_stat are
+
+ * displayed on stderr, each preceeded by "GSS-API error <msg>: " and
+
+ * followed by a newline.
+
+ */
+
+void
+
+display_status (char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) {
+
+    display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
+
+    display_status_1(msg, min_stat, GSS_C_MECH_CODE);
+
+}
+
+
+
+static void
+
+display_status_1(char *m, OM_uint32 code, int type) {
+
+    OM_uint32 maj_stat, min_stat;
+
+    gss_buffer_desc msg;
+
+    #ifdef GSSAPI_V2
+
+        OM_uint32 msg_ctx;
+
+    #else      /* GSSAPI_V2 */
+
+        int msg_ctx;
+
+    #endif     /* GSSAPI_V2 */
+
+     
+
+    msg_ctx = 0;
+
+    while (1) {
+
+        maj_stat = gss_display_status(
+
+               &min_stat, code, type, GSS_C_NULL_OID, &msg_ctx, &msg);
+
+
+
+        fprintf (stderr, "GSS-API error %s: %s\r", m, (char *)msg.value);
+
+        
+
+        (void) gss_release_buffer(&min_stat, &msg);
+
+         
+
+        if (!msg_ctx)
+
+            break;
+
+    }
+
+} /* display_status */
+
diff --git a/src/mac/gss-sample/gss-sample.sit.hqx b/src/mac/gss-sample/gss-sample.sit.hqx
new file mode 100644 (file)
index 0000000..2927c31
--- /dev/null
@@ -0,0 +1,48 @@
+(This file must be converted with BinHex 4.0)
+:$QGcFbecB@e`E'8ZFfPd!&0*9%46593K!!!!!!G*!!!"4V`K8dP8)3!#!!!(5A*
+-BA8#!3!!!"B!!!d0$%G68b"6B@e`E'8ZYA0bB`!!!!!!!!!!!!!!!!!!!!$I'J!
+!!!!!!!!!!!!!!!!!!!!!!!!!"T!!!!!!!2rrrrp069"568e$3`%!V$aa3kb3!*a
++!!!*m3!!#U)!!!)e!!!$eD"kNV-!!!!!!!!50#0%$L)Uq`C4+5ScT300hITKF$j
+mZT@4#)Y)kBc#IAqDGT+61M[$hCfGJB#$FQr3Y(I`EJH2,0X8)#UrMFMpYaB"!e"
+Z*bT'CFE6IDpqD1,9S*JFF&HPm`50Sa-cDlN1cNZ4D2Gdp%H+TZGb"82F$!Y6@pJ
+!#pY[B3-&aPaKUe"XUffBBQd&ICkFP[Cc9(5!0Qb3!&ACP#9&hXcrr4$mrYfi`6!
+PhIar5%[k09a2bkTNrPIlq(BLd6qpC,c8F0JDGl'5*U,eqrpI`IhcBi4c#C[Sf1e
+`1Xmpb[HPSVp6C3@,HFED&4k'h[qrIH84i'9LUM8PRCSUaE3r"X&6,C8l[ZJF(ZN
+l(ed1V!@&LahS1"&X13FHKB,b2EclEl6D'#UfjIpqZD!#9G(QIBV2Reaj@()T1G'
+4bb&XbGkA3483ip+P5f8eTQ6MI'QIhVY`U@H-S&Zk9*&lG8QAZE(d1"!"68`DKT5
+4PbDjbR8jYR6#-4Ve)(-S1#-Qa9,m'+IDjQ!1UT(d@"`ra"14a6dRq$R2r&XY@p!
+6c!4SaDUb[bI&qY51R[Vrbj,Va2cp(iArm'-(0p*hR4-FV`YSbeDL5&SJp)c&(UV
+MP`EcRE[D*S9!-6R'jImS'%Eq+"c*re%iqArlSk!Gqk0!6`h1GNrr,R$2@KJV-1N
+D9ePB['f3!'*Q#q-YE+U&+5eXYS@T,B`Q60`@GXR#pJK-CCmX#J[c'jd4jJl,AT1
+9`8X#-i4eE512Q3aj@f90I4m!!!X!YrCqjZ8PNc$#MM$*d`JMJl8MaeC#Mc#6X*-
+``XiMc#6d#205GREN+'&(MTeiLNqbRS3kL1![*U&('$Pf*Q'%(@(Nf*PN`2c)-I+
+8X*-`mN`*)j3FNi`BHAD5Ta&+'+'4b8U15Bk4Cq3CB8FQ02,X##22##2(b+h!I8N
+"++'%HB3HRP#C(D%5GZ3B1AEN'%%*!b"i))$$kM+m')f'%%)B[N8)f5VKH`cZI2$
+0KZm`bN*PS$fj)EPG%44C8XZ(iIll)E`LXaSpUiM552A0$Ck*q61$[i#UrZ3aTJF
+0QPkMQT%5K$pIQRpB-@lDIh%,[FSqk%,SbML`I[1b2Ma$k2+3!2E3NeFP+MfGX@K
+9f&pKK1#i"b*)r5h`r**Um(Cp3@MVm5@HU)J'$rG$L)8TRNAM*CqrQcCi19CJ@P-
+m@e@(dVkl5P!Mj3B2Yli%9C,Lf4P2&!8a+"P$4dLk[`,1Jil!eI4GET-J0VGiBCD
+0M-DQBU@BG)eQL9%he4aTD5Mf9-JPa3HpPAX1HaXAq@06MIQFQU94Qi4B%%J!T1a
+PDYFK6XeQ9%G,3r1*eK@A'[ATp4fFQX2bYN-el44$XK5*H9I'06i`r*&6cBcUj&4
+&AClcq%"AQ&-YM'SMe,#XLUY1UGF16V@bA#eUc#p([F'ebSc[2E#0YM`lZC!!%B'
+$9k&66Q2MjbEIF+U0HE@U-8@1"0,8XFQhTcJeMq@D!ekrj80b(GV-Fl9$Uj!!S-+
+#U%E&MM9br)DePP-GfM4)LK*CRiEl-mj(2+&mQ(-bYQ`(@8qSq`AhkY5R`3rJY&R
+`qTKlG@N*pA3*SI9j'([B0mfT"ArRP5INCP3ASji*5"&*NF8PHRbJVj96S5UKjhZ
+4(rc2[k)hQAjIT-'T3r8`9fimHkZDI,9AEAMf0VR[eHjpH1Td+hU#%md61(&N&#I
+3HF0rCP23$pY5I[MAlJT6rZ(p#1dGK)VAr'HfKrN4qZIIcrf68jh1If2Rd3rYcMr
+qZeIp"m"cDSidrjQ04MqdGq$dSVjIrUparmA8IcmD!'hlkMqcKqQ(pMNT,0+)&j,
+)5[BId%l5aU"YC%F"l5)p#cU2E"qJ#`M[C"PbNdi%E5Il"HK"q"1LEc,cH@4f0Ie
+B01dJQiG*BEQ!TVQ!TVQ!TVQ!TVQ!TVQ!TVPmHXpb!8ec!8hQK24%DYkeA$+EM(l
+bpCX*q0)r"6Ka9H[Pl@dim3$Qd6h+lMhlm164qS@HaQCX,Ad&6$V[V+c`h"h`BDU
+$%TVaeB9S#(MZ,[ae-E[*EZ&V9'1mU'Z*m,9)J@45I`4rSN`HmSCBqJm!!!d!$fG
+cFbeME'PPER3ZFR0bB`!!!!!!!!!!!!!!!!!!!!!JS!!!!!!!!!!!!!!!!!!!!!!
+!&J!!!!!!!!!!rrrrre*68N0%Eh9R)3#VATi%V*!!GQd!!!%H!!!!!!!!!%N!!!!
+!C,B!!!!!!!!!!$"L%3!)XY&i[PR#$ejfDQCQMC6d#'A5*c*&LXIaK)*G@bIbV05
+bS0jk6lhUJ`DrhI[`f'b&I0rfp!K[I2mRqID&%Kf&3QQP,!!!!'Z2!!!"!!!!!43
+!!!!8!!!!-J!)!!%!"!!!!!N!!!!)!!%!!!!!!!`!!!!)!!%!!`!!$@aTBR*KFQP
+PFbjcDA3#!!!!8dP84&0*9#%"!2rrrrm!!&0*9%46593K!3$rrrrr!!!!!!!!!!!
+!!!!!!!!!!!!!V)p&eJ!!FJS!!!&'!!!!!!!!!!!!!"9$E'PMDb"25b"dEb"MEfj
+dD@jeC5i!!!!!!!!!T!!#!!!!!!!!!!!!!!!#!!3"!!"+!!%!!!!!!!!!!!!!!!!
+e9'mJBfpZG'PZG@8JG'KP)'0eFR*PER3JEh"PFQ&dD@pZ,#"ME'PMDb"dD'Pc)'*
+eG(4[ELi!!!!!!"!"F!$Y!Pd#hJ!!!!!!!!-!!!!"!!!!!43!!!!8!!!!-J)qMAJ
+F5!!!!"`!-J!!8f9dC`!!!!S!!2rr!!!!!!)qch3`@!:
diff --git a/src/mac/gss-sample/gss.h b/src/mac/gss-sample/gss.h
new file mode 100644 (file)
index 0000000..de71c46
--- /dev/null
@@ -0,0 +1,88 @@
+/*+*************************************************************************
+
+** 
+
+** gss.h
+
+** 
+
+***************************************************************************/
+
+/*
+
+ * Use the internal mac kerberos sockets library
+
+ * (it is 'just enough' sockets for kerberos, and perhaps other uses)
+
+ */
+
+#define socket                 krb5_socket
+
+#define closesocket            krb5_closesocket
+
+#define connect                        krb5_connect
+
+#define bind                   krb5_bind
+
+#define send                   krb5_send
+
+#define recv                   krb5_recv
+
+#define sendto                 krb5_sendto
+
+#define select                 krb5_select
+
+#define recvfrom               krb5_recvfrom
+
+#define inet_ntoa              krb5_inet_ntoa
+
+#define gethostbyname  krb5_gethostbyname
+
+#define gethostbyaddr  krb5_gethostbyaddr
+
+#define gethostname            krb5_gethostname
+
+#define getsockname            krb5_getsockname
+
+#define getmyipaddr            krb5_getmyipaddr
+
+#include "macsock.h"
+
+
+
+#include <string.h>
+
+
+
+#include "gssapi.h"
+
+#include "gssapi_generic.h"
+
+
+
+typedef unsigned short u_short;
+
+
+
+// gss-misc.c
+
+int send_token(SOCKET s, gss_buffer_t tok);
+
+int recv_token(SOCKET s, gss_buffer_t tok);
+
+void display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat);
+
+static void display_status_1(char *m, OM_uint32 code, int type);
+
+
+
+// gss-client.c
+
+int gss (char *host, char *name, char *msg, int port);
+
+int call_server(char *host, u_short port, int dov2, char *service_name, char *msg);
+
+SOCKET connect_to_server(char *host, u_short port);
+
+int client_establish_context(SOCKET s, char *service_name, gss_ctx_id_t *gss_context);
+