Adding testing CLI client (based off the Heimdal testing sample)
[mod_auth_kerb.git] / client / gss_common.c
diff --git a/client/gss_common.c b/client/gss_common.c
new file mode 100644 (file)
index 0000000..23517a7
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden). 
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ *
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software 
+ *    without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#include "client_locl.h"
+#include <gssapi.h>
+#include "gss_common.h"
+//RCSID("$Id$");
+
+void
+write_token (int sock, gss_buffer_t buf)
+{
+    uint32_t len, net_len;
+    OM_uint32 min_stat;
+
+    len = buf->length;
+
+    net_len = htonl(len);
+
+    if (net_write (sock, &net_len, 4) != 4)
+       err (1, "write");
+    if (net_write (sock, buf->value, len) != len)
+       err (1, "write");
+
+    gss_release_buffer (&min_stat, buf);
+}
+
+static void
+enet_read(int fd, void *buf, size_t len)
+{
+    ssize_t ret;
+
+    ret = net_read (fd, buf, len);
+    if (ret == 0)
+       errx (1, "EOF in read");
+    else if (ret < 0)
+       errx (1, "read");
+}
+
+void
+read_token (int sock, gss_buffer_t buf)
+{
+    uint32_t len, net_len;
+
+    enet_read (sock, &net_len, 4);
+    len = ntohl(net_len);
+    buf->length = len;
+    buf->value  = malloc(len);
+    enet_read (sock, buf->value, len);
+}
+
+void
+gss_print_errors (OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+    OM_uint32 new_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc status_string;
+    OM_uint32 ret;
+
+    do {
+       ret = gss_display_status(&new_stat,
+                                maj_stat,
+                                GSS_C_GSS_CODE,
+                                GSS_C_NO_OID,
+                                &msg_ctx,
+                                &status_string);
+       fprintf (stderr, "%.*s\n", (int)status_string.length,
+                (char *)status_string.value);
+       gss_release_buffer(&new_stat, &status_string);
+    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+
+    msg_ctx = 0;
+    do {
+       ret = gss_display_status (&new_stat,
+                                 min_stat,
+                                 GSS_C_MECH_CODE,
+                                 GSS_C_NO_OID,
+                                 &msg_ctx,
+                                 &status_string);
+       fprintf (stderr, "%.*s\n", (int)status_string.length, 
+                (char *)status_string.value);
+       gss_release_buffer (&new_stat, &status_string);
+    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+void
+gss_verr(int exitval, OM_uint32 maj_stat, OM_uint32 min_stat, const char *fmt, va_list ap)
+{
+    vwarnx (fmt, ap);
+    gss_print_errors (maj_stat, min_stat);
+    exit (exitval);
+}
+
+void
+gss_err(int exitval, OM_uint32 maj_stat, OM_uint32 min_stat, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    gss_verr (exitval, maj_stat, min_stat, fmt, args);
+    va_end(args);
+}
+
+gss_OID
+select_mech(const char *mech)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc tok;
+    gss_OID oid;
+
+#if 0
+    if (strcasecmp(mech, "krb5") == 0)
+       return GSS_KRB5_MECHANISM;
+    if (strcasecmp(mech, "spnego") == 0)
+       return GSS_SPNEGO_MECHANISM;
+#endif
+    if (strcasecmp(mech, "no-oid") == 0)
+       return GSS_C_NO_OID;
+
+    tok.value = (char *) mech;
+    tok.length = strlen(tok.value);
+    maj_stat = gss_str_to_oid(&min_stat, &tok, &oid);
+    if (GSS_ERROR(maj_stat)) {
+       gss_err(1, maj_stat, min_stat, "Unknown gssapi mechanims required");
+       exit(1);
+    }
+
+    return oid;
+}
+
+void
+print_gss_name(const char *prefix, gss_name_t name)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc name_token;
+
+    maj_stat = gss_display_name (&min_stat,
+                                name,
+                                &name_token,
+                                NULL);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, maj_stat, min_stat, "gss_display_name");
+
+    fprintf (stderr, "%s `%.*s'\n", prefix,
+            (int)name_token.length,
+            (char *)name_token.value);
+
+    gss_release_buffer (&min_stat, &name_token);
+
+}