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