]> eyrie.org Git - kerberos/perl-kerberos.git/commitdiff
Move Kerberos croak function into a utility library
authorRuss Allbery <eagle@eyrie.org>
Thu, 6 Mar 2014 21:05:15 +0000 (13:05 -0800)
committerRuss Allbery <eagle@eyrie.org>
Thu, 6 Mar 2014 21:06:12 +0000 (13:06 -0800)
Rename kadmin_croak to krb5_croak and move it into a utility
library.  We will want to use it for Authen::Kerberos as well
as Authen::Kerberos::Kadmin.

Build.PL
lib/Authen/Kerberos/Kadmin.xs
portable/macros.h [new file with mode: 0644]
util/croak.c [new file with mode: 0644]
util/util.h [new file with mode: 0644]

index 4a8847a708e60fe68bedc336637548907e1be47e..26c71de76247645811c3e848db239f7cf93a7d3a 100644 (file)
--- a/Build.PL
+++ b/Build.PL
@@ -47,6 +47,7 @@ my $build = Module::Build->new(
     recursive_test_files => 1,
 
     # XS configuration.
+    c_source             => 'util',
     extra_compiler_flags => [split(q{ }, $compiler_flags)],
     extra_linker_flags   => [split(q{ }, $linker_flags)],
 
index 10f17a4e95a039dec2b671e8258d930b4382ee98..23dbef3de27e590e7998bf85ab543228ca77498d 100644 (file)
@@ -61,39 +61,6 @@ typedef struct {
 #define CROAK_NULL_SELF(o, t, f) CROAK_NULL((o), t, t "::" f)
 
 
-/*
- * Turn a Kerberos error into a Perl exception.  If the destroy argument is
- * true, free the Kerberos context after setting up the exception.  This is
- * used in cases where we're croaking inside the constructor.
- */
-static void __attribute__((__noreturn__))
-kadmin_croak(krb5_context ctx, krb5_error_code code, const char *function,
-             bool destroy)
-{
-    HV *hv;
-    SV *rv;
-    const char *message;
-
-    hv = newHV();
-    (void) hv_stores(hv, "code", newSViv(code));
-    message = krb5_get_error_message(ctx, code);
-    (void) hv_stores(hv, "message", newSVpv(message, 0));
-    krb5_free_error_message(ctx, message);
-    if (destroy)
-        krb5_free_context(ctx);
-    if (function != NULL)
-        (void) hv_stores(hv, "function", newSVpv(function, 0));
-    if (CopLINE(PL_curcop)) {
-        (void) hv_stores(hv, "line", newSViv(CopLINE(PL_curcop)));
-        (void) hv_stores(hv, "file", newSVpv(CopFILE(PL_curcop), 0));
-    }
-    rv = newRV_noinc((SV *) hv);
-    sv_bless(rv, gv_stashpv("Authen::Kerberos::Exception", TRUE));
-    sv_setsv(get_sv("@", TRUE), sv_2mortal(rv));
-    croak(Nullch);
-}
-
-
 /* XS code below this point. */
 
 MODULE = Authen::Kerberos::Kadmin       PACKAGE = Authen::Kerberos::Kadmin
@@ -119,7 +86,7 @@ new(class, args)
 {
     code = krb5_init_context(&ctx);
     if (code != 0)
-        kadmin_croak(NULL, code, "krb5_init_context", FALSE);
+        krb5_croak(NULL, code, "krb5_init_context", FALSE);
 
     /* Parse the arguments to the function, if any. */
     memset(&params, 0, sizeof(params));
@@ -134,12 +101,12 @@ new(class, args)
             config_file = SvPV_nolen(*value);
             code = krb5_prepend_config_files_default(config_file, &files);
             if (code != 0)
-                kadmin_croak(ctx, code, "krb5_prepend_config_files_default",
-                             TRUE);
+                krb5_croak(ctx, code, "krb5_prepend_config_files_default",
+                           TRUE);
             code = krb5_set_config_files(ctx, files);
             krb5_free_config_files(files);
             if (code != 0)
-                kadmin_croak(ctx, code, "krb5_set_config_files", TRUE);
+                krb5_croak(ctx, code, "krb5_set_config_files", TRUE);
         }
 
         /* Set configuration parameters used by kadm5_init. */
@@ -170,7 +137,7 @@ new(class, args)
                                         &params,  KADM5_STRUCT_VERSION,
                                         KADM5_API_VERSION_2, &handle);
     if (code != 0)
-        kadmin_croak(ctx, code, "kadm5_init_with_password_ctx", TRUE);
+        krb5_croak(ctx, code, "kadm5_init_with_password_ctx", TRUE);
 
     /* Set up password quality checking if desired. */
     if (quality)
@@ -219,7 +186,7 @@ chpass(self, principal, password)
 {
     code = krb5_parse_name(self->ctx, principal, &princ);
     if (code != 0)
-        kadmin_croak(self->ctx, code, "krb5_parse_name", FALSE);
+        krb5_croak(self->ctx, code, "krb5_parse_name", FALSE);
 
     /*
      * If configured to do quality checking, we need to do that manually,
@@ -231,7 +198,7 @@ chpass(self, principal, password)
         reason = kadm5_check_password_quality(self->ctx, princ, &pwd_data);
         if (reason != NULL) {
             krb5_set_error_message(self->ctx, KADM5_PASS_Q_DICT, "%s", reason);
-            kadmin_croak(self->ctx, KADM5_PASS_Q_DICT,
+            krb5_croak(self->ctx, KADM5_PASS_Q_DICT,
                          "kadm5_check_password_quality", FALSE);
         }
     }
@@ -240,6 +207,6 @@ chpass(self, principal, password)
     code = kadm5_chpass_principal(self->handle, princ, password);
     krb5_free_principal(self->ctx, princ);
     if (code != 0)
-        kadmin_croak(self->ctx, code, "kadm5_chpass_principal", FALSE);
+        krb5_croak(self->ctx, code, "kadm5_chpass_principal", FALSE);
     XSRETURN_YES;
 }
diff --git a/portable/macros.h b/portable/macros.h
new file mode 100644 (file)
index 0000000..b5093f5
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Portability macros used in include files.
+ *
+ * The canonical version of this file is maintained in the rra-c-util package,
+ * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ *
+ * The authors hereby relinquish any claim to any copyright that they may have
+ * in this work, whether granted under contract or by operation of law or
+ * international treaty, and hereby commit to the public, at large, that they
+ * shall not, at any time in the future, seek to enforce any copyright in this
+ * work against any person or entity, or prevent any person or entity from
+ * copying, publishing, distributing or creating derivative works of this
+ * work.
+ */
+
+#ifndef PORTABLE_MACROS_H
+#define PORTABLE_MACROS_H 1
+
+/*
+ * __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7
+ * could you use the __format__ form of the attributes, which is what we use
+ * (to avoid confusion with other macros).
+ */
+#ifndef __attribute__
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#  define __attribute__(spec)   /* empty */
+# endif
+#endif
+
+/*
+ * We use __alloc_size__, but it was only available in fairly recent versions
+ * of GCC.  Suppress warnings about the unknown attribute if GCC is too old.
+ * We know that we're GCC at this point, so we can use the GCC variadic macro
+ * extension, which will still work with versions of GCC too old to have C99
+ * variadic macro support.
+ */
+#if !defined(__attribute__) && !defined(__alloc_size__)
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
+#  define __alloc_size__(spec, args...) /* empty */
+# endif
+#endif
+
+/*
+ * LLVM and Clang pretend to be GCC but don't support all of the __attribute__
+ * settings that GCC does.  For them, suppress warnings about unknown
+ * attributes on declarations.  This unfortunately will affect the entire
+ * compilation context, but there's no push and pop available.
+ */
+#if !defined(__attribute__) && (defined(__llvm__) || defined(__clang__))
+# pragma GCC diagnostic ignored "-Wattributes"
+#endif
+
+/*
+ * BEGIN_DECLS is used at the beginning of declarations so that C++
+ * compilers don't mangle their names.  END_DECLS is used at the end.
+ */
+#undef BEGIN_DECLS
+#undef END_DECLS
+#ifdef __cplusplus
+# define BEGIN_DECLS    extern "C" {
+# define END_DECLS      }
+#else
+# define BEGIN_DECLS    /* empty */
+# define END_DECLS      /* empty */
+#endif
+
+#endif /* !PORTABLE_MACROS_H */
diff --git a/util/croak.c b/util/croak.c
new file mode 100644 (file)
index 0000000..5df70fd
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Utility functions for XS code to throw proper exceptions.
+ *
+ * All Authen::Kerberos modules throw Authen::Kerberos::Exception exceptions
+ * on failure.  This is a helper function for XS code to construct such an
+ * exception from an error code and additional information.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2014
+ *     The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <EXTERN.h>
+#include <perl.h>
+#include <XSUB.h>
+
+#include <krb5.h>
+
+
+/*
+ * Turn a Kerberos error into a Perl exception.  If the destroy argument is
+ * true, free the Kerberos context after setting up the exception.  This is
+ * used in cases where we're croaking inside the constructor.
+ */
+void
+krb5_croak(krb5_context ctx, krb5_error_code code, const char *function,
+           bool destroy)
+{
+    HV *hv;
+    SV *rv;
+    const char *message;
+
+    hv = newHV();
+    (void) hv_stores(hv, "code", newSViv(code));
+    message = krb5_get_error_message(ctx, code);
+    (void) hv_stores(hv, "message", newSVpv(message, 0));
+    krb5_free_error_message(ctx, message);
+    if (destroy)
+        krb5_free_context(ctx);
+    if (function != NULL)
+        (void) hv_stores(hv, "function", newSVpv(function, 0));
+    if (CopLINE(PL_curcop)) {
+        (void) hv_stores(hv, "line", newSViv(CopLINE(PL_curcop)));
+        (void) hv_stores(hv, "file", newSVpv(CopFILE(PL_curcop), 0));
+    }
+    rv = newRV_noinc((SV *) hv);
+    sv_bless(rv, gv_stashpv("Authen::Kerberos::Exception", TRUE));
+    sv_setsv(get_sv("@", TRUE), sv_2mortal(rv));
+    croak(Nullch);
+}
diff --git a/util/util.h b/util/util.h
new file mode 100644 (file)
index 0000000..0312fdb
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Extra utility functions for Kerberos Perl bindings.
+ *
+ * Prototypes for various utility functions used by multiple Kerberos XS
+ * modules, collected together to avoid code duplication.
+ *
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2014
+ *     The Board of Trustees of the Leland Stanford Junior University
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef UTIL_UTIL_H
+#define UTIL_UTIL_H 1
+
+#include <portable/macros.h>
+
+#include <krb5.h>               /* krb5_contxt, krb5_error_code */
+#include <perl.h>               /* bool */
+
+BEGIN_DECLS
+
+/* Default to a hidden visibility for all util functions. */
+#pragma GCC visibility push(hidden)
+
+/*
+ * Given a Kerberos context, an error code, and the Kerberos function that
+ * failed, construct an Authen::Kerberos::Exception object and throw it using
+ * croak.  The final boolean argument says whether to free the context before
+ * calling croak.
+ */
+void krb5_croak(krb5_context, krb5_error_code, const char *function,
+                bool destroy)
+    __attribute__((__noreturn__));
+
+/* Undo default visibility change. */
+#pragma GCC visibility pop
+
+END_DECLS
+
+#endif /* UTIL_UTIL_H */