Revision: 1921
          
http://undernet-ircu.svn.sourceforge.net/undernet-ircu/?rev=1921&view=rev
Author:   klmitch
Date:     2009-08-01 01:06:19 +0000 (Sat, 01 Aug 2009)

Log Message:
-----------
Begin implementation of a complete authorization system.  The idea is to
organize authorization checks into sets of checks, then call authz() on
those sets.  authz() is even coded to reply with a message, so we can
simply return if authz() returns AUTH_DENY (which has code 0x0000).

Modified Paths:
--------------
    ircu2/branches/authz/ChangeLog
    ircu2/branches/authz/include/channel.h
    ircu2/branches/authz/include/client.h
    ircu2/branches/authz/ircd/Makefile.am
    ircu2/branches/authz/ircd/channel.c
    ircu2/branches/authz/ircd/client.c

Added Paths:
-----------
    ircu2/branches/authz/include/authz.h
    ircu2/branches/authz/ircd/authz.c

Modified: ircu2/branches/authz/ChangeLog
===================================================================
--- ircu2/branches/authz/ChangeLog      2009-07-31 21:24:09 UTC (rev 1920)
+++ ircu2/branches/authz/ChangeLog      2009-08-01 01:06:19 UTC (rev 1921)
@@ -1,3 +1,21 @@
+2009-07-31  Kevin L. Mitchell  <[email protected]>
+
+       * include/authz.h: declaration of the authorization system
+
+       * ircd/authz.c: implementation of authz() master authorization
+       check function
+
+       * include/client.h: declare authz_oper, authz_globop, and
+       authz_priv
+
+       * include/channel.h: declare authz_chanop and authz_hasvoice
+
+       * ircd/client.c: define authz_oper, authz_globop, and authz_priv
+
+       * ircd/channel.c: define authz_chanop and authz_hasvoice
+
+       * ircd/Makefile.am (ircd_SOURCES): compile authz.c
+
 2008-03-27  Kevin L. Mitchell  <[email protected]>
 
        * ircd/watch.c: implementation of generic watch subsystem

Added: ircu2/branches/authz/include/authz.h
===================================================================
--- ircu2/branches/authz/include/authz.h                                (rev 0)
+++ ircu2/branches/authz/include/authz.h        2009-08-01 01:06:19 UTC (rev 
1921)
@@ -0,0 +1,169 @@
+/*
+ * IRC - Internet Relay Chat, include/authz.h
+ * Copyright (C) 2009 Kevin L. Mitchell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/** @file
+ * @brief Structures and functions for handling client authorization.
+ * @version $Id$
+ */
+#ifndef INCLUDED_authz_h
+#define INCLUDED_authz_h
+#ifndef INCLUDED_client_h
+#include "client.h"
+#endif
+#ifndef INCLUDED_stdarg_h
+#include <stdarg.h>    /* va_list */
+#define INCLUDED_stdarg_h
+#endif
+
+/** Describes an authorization check. */
+typedef struct AuthZ authz_t;
+/** Describes a set of authorization checks. */
+typedef struct AuthZSet authzset_t;
+
+/** Authorization check callback for authz().
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+typedef unsigned int (*authz_check_t)(struct Client* client,
+                                     unsigned int flags,
+                                     authz_t* authz,
+                                     va_list vl);
+
+/** Describes an authorization check. */
+struct AuthZ {
+  unsigned long        az_magic;       /**< Magic number */
+  authz_check_t*az_check;      /**< Check callback */
+  void*                az_e_ptr;       /**< Extra pointer data for use by 
az_check */
+  unsigned int az_e_int;       /**< Extra integer data for use by az_check */
+};
+
+/** Magic number for authz_t. */
+#define AUTHZ_MAGIC            0x4bae2e0e
+
+/** Initialize an authz_t.
+ * @param[in] check Callback for checking authorization.
+ * @param[in] e_ptr Extra pointer data for use by check.
+ * @param[in] e_int Extra integer data for use by check.
+ */
+#define AUTHZ_INIT(check, e_ptr, e_int)                \
+  { AUTHZ_MAGIC, (check), (e_ptr), (e_int) }
+
+/** Check the authz_t magic number. */
+#define AUTHZ_CHECK(az)                ((az) && (az)->az_magic == AUTHZ_MAGIC)
+
+/** Authorization denied. */
+#define AUTHZ_DENY             0x0000
+/** Pass on authorization check. */
+#define AUTHZ_PASS             0x0001
+/** Authorization granted. */
+#define AUTHZ_GRANT            0x0002
+/** Mask authorization return values. */
+#define AUTHZ_MASK             0x0003
+
+/** If set, indicates that a message has already been sent to the
+ * client indicating the authorization failure.
+ */
+#define AUTHZ_MSGSENT          0x0010
+
+/** Retrieve check function pointer.
+ * @param[in] az Pointer to authz_t.
+ * @return Pointer to authorization check function.
+ */
+#define az_check(az)           ((az)->az_check)
+
+/** Retrieve extra pointer data.
+ * @param[in] az Pointer to authz_t.
+ * @return Extra pointer data.
+ */
+#define az_e_ptr(az)           ((az)->az_e_ptr)
+
+/** Retrieve extra integer data.
+ * @param[in] az Pointer to authz_t.
+ * @return Extra integer data.
+ */
+#define az_e_int(az)           ((az)->az_e_int)
+
+/** Describes a set of authorization checks. */
+struct AuthZSet {
+  unsigned long        azs_magic;      /**< Magic number */
+  unsigned int azs_mode;       /**< Authorization mode */
+  authz_t**    azs_set;        /**< NULL-terminated list of authz_t
+                                    pointers. */
+};
+
+/** Magic number for authzset_t. */
+#define AUTHZSET_MAGIC         0x8a5ce114
+
+/** Initialize an authzset_t.
+ * @param[in] mode Set mode; can be one of AUTHZ_AND or AUTHZ_OR.
+ * @param[in] set NULL-terminated array of authz_t pointers.
+ */
+#define AUTHZSET_INIT(mode, set)               \
+  { AUTHZSET_MAGIC, (mode), (set) }
+
+/** Check the authzset_t magic number. */
+#define AUTHZSET_CHECK(azs)    ((azs) && (azs)->azs_magic == AUTHZSET_MAGIC)
+
+/** Authorization set is checked in short-circuiting AND mode--all
+ * checks must return AUTHZ_GRANT or AUTHZ_PASS.  If all checks return
+ * AUTHZ_PASS, authorization is denied.
+ */
+#define AUTHZ_AND      0x0000
+/** Authorization set is checked in short-circuiting OR mode--the
+ * first check that returns AUTHZ_GRANT causes authorization to be
+ * granted.  If all checks return AUTHZ_PASS, authorization is
+ * denied.  AUTHZ_DENY is ignored, except that it will force
+ * authorization to be denied even if the AUTHZ_ACCEPT flag is set and
+ * all other checks returned AUTHZ_PASS.
+ */
+#define AUTHZ_OR       0x0001
+
+/** Mask for the mode. */
+#define AUTHZ_MODEMASK 0x0003
+
+/** If set on mode, changes the default authorization return to grant
+ * authorization if all checks return with AUTHZ_PASS.
+ */
+#define AUTHZ_ACCEPT   0x0010
+
+/** If set on flags, inhibits the sending of authorization denied
+ * messages to the user.
+ */
+#define AUTHZ_NOMSG    0x8000
+
+/** If set on flags, causes AUTHZ_PASS to be returned if all checks
+ * returned AUTHZ_PASS.  This is used for chaining authorization sets.
+ */
+#define AUTHZ_PASSTHRU 0x4000
+
+/** Check client authorization.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @return Boolean TRUE if authorization is granted, else FALSE.
+ */
+extern unsigned int authz(struct Client* client, unsigned int flags,
+                         authzset_t* set, ...);
+
+#endif /* INCLUDED_authz_h */


Property changes on: ircu2/branches/authz/include/authz.h
___________________________________________________________________
Added: svn:keywords
   + Id

Modified: ircu2/branches/authz/include/channel.h
===================================================================
--- ircu2/branches/authz/include/channel.h      2009-07-31 21:24:09 UTC (rev 
1920)
+++ ircu2/branches/authz/include/channel.h      2009-08-01 01:06:19 UTC (rev 
1921)
@@ -23,6 +23,9 @@
  */
 #ifndef INCLUDED_channel_h
 #define INCLUDED_channel_h
+#ifndef INCLUDED_authz_h
+#include "authz.h"
+#endif
 #ifndef INCLUDED_ircd_defs_h
 #include "ircd_defs.h"        /* NICKLEN */
 #endif
@@ -358,6 +361,9 @@
 extern struct Channel* GlobalChannelList;
 extern int             LocalChanOperMode;
 
+extern authz_t* authz_chanop;
+extern authz_t* authz_hasvoice;
+
 /*
  * Proto types
  */

Modified: ircu2/branches/authz/include/client.h
===================================================================
--- ircu2/branches/authz/include/client.h       2009-07-31 21:24:09 UTC (rev 
1920)
+++ ircu2/branches/authz/include/client.h       2009-08-01 01:06:19 UTC (rev 
1921)
@@ -23,6 +23,9 @@
  */
 #ifndef INCLUDED_client_h
 #define INCLUDED_client_h
+#ifndef INCLUDED_authz_h
+#include "authz.h"
+#endif
 #ifndef INCLUDED_ircd_defs_h
 #include "ircd_defs.h"
 #endif
@@ -717,6 +720,10 @@
 #define HIDE_IP 0 /**< Do not show IP address in get_client_name() */
 #define SHOW_IP 1 /**< Show ident and IP address in get_client_name() */
 
+extern authz_t* authz_oper;
+extern authz_t* authz_globop;
+extern authz_t* authz_priv[];
+
 extern const char* get_client_name(const struct Client* sptr, int showip);
 extern const char* client_get_default_umode(const struct Client* sptr);
 extern int client_get_ping(const struct Client* local_client);

Modified: ircu2/branches/authz/ircd/Makefile.am
===================================================================
--- ircu2/branches/authz/ircd/Makefile.am       2009-07-31 21:24:09 UTC (rev 
1920)
+++ ircu2/branches/authz/ircd/Makefile.am       2009-08-01 01:06:19 UTC (rev 
1921)
@@ -46,6 +46,7 @@
 nodist_ircd_SOURCES = version.c
 ircd_SOURCES = \
        IPcheck.c \
+       authz.c \
        channel.c \
        class.c \
        client.c \

Added: ircu2/branches/authz/ircd/authz.c
===================================================================
--- ircu2/branches/authz/ircd/authz.c                           (rev 0)
+++ ircu2/branches/authz/ircd/authz.c   2009-08-01 01:06:19 UTC (rev 1921)
@@ -0,0 +1,106 @@
+/*
+ * IRC - Internet Relay Chat, ircd/authz.c
+ * Copyright (C) 2009 Kevin L. Mitchell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/** @file
+ * @brief Implementation of client authorization.
+ * @version $Id$
+ */
+#include "config.h"
+
+#include "authz.h"
+#include "client.h"
+#include "ircd_log.h"
+#include "ircd_reply.h"
+
+#include <stdarg.h>
+
+unsigned int
+authz(struct Client* client, unsigned int flags, authzset_t *set, ...)
+{
+  va_list vl;
+  authz_t *authz;
+  int i, ret = 0, def = AUTHZ_DENY;
+
+  /* Sanity-check our arguments */
+  if (!client || !AUTHZSET_CHECK(set))
+    return AUTHZ_DENY;
+
+  /* Update the default return value */
+  if (flags & AUTHZ_PASSTHRU)
+    def = AUTHZ_PASS;
+  else if (set->azs_mode & AUTHZ_ACCEPT)
+    def = AUTHZ_GRANT;
+
+  /* Walk the authorization chain */
+  for (i = 0; set->azs_set[i]; i++) {
+    authz = set->azs_set[i];
+
+    assert(AUTHZ_CHECK(authz));
+
+    /* Do we even have a check routine? */
+    if (authz->az_check) {
+      va_start(vl, authz);
+      ret = (*authz->az_check)(client, flags, authz, vl); /* call it */
+      va_end(vl);
+    } else /* use the extra integer data */
+      ret = az_e_int(authz);
+
+    assert((ret & AUTHZ_MASK) == AUTHZ_DENY ||
+          (ret & AUTHZ_MASK) == AUTHZ_PASS ||
+          (ret & AUTHZ_MASK) == AUTHZ_GRANT)
+
+    /* OK, what do we do now? */
+    switch (ret & AUTHZ_MASK) {
+    case AUTHZ_GRANT: /* authorization granted */
+      if ((set->azs_mode & AUTHZ_MODEMASK) == AUTHZ_OR)
+       return ret;
+
+      /* OK, we're in AND mode, just change the default */
+      def = AUTHZ_GRANT;
+      break;
+
+    case AUTHZ_DENY: /* authorization denied */
+      if ((set->azs_mode & AUTHZ_MODEMASK) == AUTHZ_AND) {
+       if (!(flags & AUTHZ_NOMSG) && !(ret & AUTHZ_MSGSENT)) {
+         /* Send the authorization denied message */
+         send_reply(client, ERR_NOPRIVILEGES);
+
+         ret |= AUTHZ_MSGSENT; /* mark that we sent the message */
+       }
+
+       return ret;
+      }
+
+      /* OK, we're in OR mode, just change the default */
+      def = AUTHZ_DENY;
+      break;
+    }
+  }
+
+  assert(def == AUTHZ_DENY || def == AUTHZ_PASS || def == AUTHZ_GRANT);
+
+  /* OK, we're going to return def; if it's AUTHZ_DENY, let's send a message */
+  if (def == AUTHZ_GRANT && !(flags & AUTHZ_NOMSG)) {
+    /* Send the authorization denied message */
+    send_reply(client, ERR_NOPRIVILEGES);
+
+    def |= AUTHZ_MSGSENT; /* mark that we sent the message */
+  }
+
+  return def; /* Return the default return value */
+}


Property changes on: ircu2/branches/authz/ircd/authz.c
___________________________________________________________________
Added: svn:keywords
   + Id

Modified: ircu2/branches/authz/ircd/channel.c
===================================================================
--- ircu2/branches/authz/ircd/channel.c 2009-07-31 21:24:09 UTC (rev 1920)
+++ ircu2/branches/authz/ircd/channel.c 2009-08-01 01:06:19 UTC (rev 1921)
@@ -24,6 +24,7 @@
 #include "config.h"
 
 #include "channel.h"
+#include "authz.h"
 #include "client.h"
 #include "destruct_event.h"
 #include "hash.h"
@@ -3642,3 +3643,49 @@
 
   cli_last_part(sptr) = CurrentTime;
 }
+
+/* Authorization stuff */
+
+/** Check client for channel operator status.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+static unsigned int
+check_chanop(struct Client* client, unsigned int flags, authz_t* authz,
+              va_list vl)
+{
+  /* Get the channel... */
+  channel = va_arg(vl, struct Channel*);
+
+  return is_chan_op(client, channel) ? AUTHZ_GRANT : AUTHZ_DENY;
+}
+
+/** Check if client has a voice.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+static unsigned int
+check_hasvoice(struct Client* client, unsigned int flags, authz_t* authz,
+              va_list vl)
+{
+  /* Get the channel... */
+  channel = va_arg(vl, struct Channel*);
+
+  return client_can_send_to_channel(client, channel, 0) ?
+    AUTHZ_GRANT : AUTHZ_DENY;
+}
+
+/** Authorization check for channel operator status. */
+authz_t* authz_chanop = AUTHZ_INIT(check_chanop, 0, 0);
+/** Authorization check for channel voice status. */
+authz_t* authz_hasvoice = AUTHZ_INIT(check_hasvoice, 0, 0);

Modified: ircu2/branches/authz/ircd/client.c
===================================================================
--- ircu2/branches/authz/ircd/client.c  2009-07-31 21:24:09 UTC (rev 1920)
+++ ircu2/branches/authz/ircd/client.c  2009-08-01 01:06:19 UTC (rev 1921)
@@ -23,6 +23,7 @@
 #include "config.h"
 
 #include "client.h"
+#include "authz.h"
 #include "class.h"
 #include "ircd.h"
 #include "ircd_features.h"
@@ -264,3 +265,71 @@
 
   return 0;
 }
+
+/* Authorization stuff */
+
+/** Check client for operator status.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+static unsigned int
+check_oper(struct Client* client, unsigned int flags, authz_t* authz,
+          va_list vl)
+{
+  return IsAnOper(client) ? AUTHZ_GRANT : AUTHZ_DENY;
+}
+
+/** Check client for global operator status.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+static unsigned int
+check_globop(struct Client* client, unsigned int flags, authz_t* authz,
+            va_list vl)
+{
+  return IsOper(client) ? AUTHZ_GRANT : AUTHZ_DENY;
+}
+
+/** Check client privileges.
+ * @param[in] client Client for which authorization is being checked.
+ * @param[in] flags Flags affecting the check.  In particular,
+ * AUTHZ_NOMSG should inhibit sending messages to clients.
+ * @param[in] authz Authorization to check.
+ * @param[in] vl Optional extra parameters passed to authz().
+ * @return AUTHZ_DENY to deny authorization, AUTHZ_PASS to continue
+ * checking authorizations, or AUTHZ_GRANT to grant authorization.
+ */
+static unsigned int
+check_priv(struct Client* client, unsigned int flags, authz_t* authz,
+          va_list vl)
+{
+  return HasPriv(client, az_e_int(authz)) ? AUTHZ_GRANT : AUTHZ_DENY;
+}
+
+/** Authorization check for oper status. */
+authz_t* authz_oper = AUTHZ_INIT(check_oper, 0, 0);
+/** Authorization check for global oper status. */
+authz_t* authz_globop = AUTHZ_INIT(check_globop, 0, 0);
+/** Authorization check table for various privileges. */
+authz_t* authz_priv[] = {
+#define P(priv) AUTHZ_INIT(check_priv, 0, PRIV_ ## priv)
+  P(CHAN_LIMIT),     P(MODE_LCHAN),     P(WALK_LCHAN),    P(DEOP_LCHAN),
+  P(SHOW_INVIS),     P(SHOW_ALL_INVIS), P(UNLIMIT_QUERY), P(KILL),
+  P(LOCAL_KILL),     P(REHASH),         P(RESTART),       P(DIE),
+  P(GLINE),          P(LOCAL_GLINE),    P(JUPE),          P(LOCAL_JUPE),
+  P(OPMODE),         P(LOCAL_OPMODE),   P(SET),           P(WHOX),
+  P(BADCHAN),        P(LOCAL_BADCHAN),  P(SEE_CHAN),      P(PROPAGATE),
+  P(DISPLAY),        P(SEE_OPERS),      P(WIDE_GLINE),    P(LIST_CHAN),
+  P(FORCE_OPMODE),   P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE)
+#undef P
+};


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.
_______________________________________________
Patches mailing list
[email protected]
http://undernet.sbg.org/mailman/listinfo/patches

Reply via email to