Forgotten changes implementing LCAS support and LB plugin for LCAS
authorDaniel Kouřil <kouril@ics.muni.cz>
Fri, 25 Jul 2008 10:48:29 +0000 (10:48 +0000)
committerDaniel Kouřil <kouril@ics.muni.cz>
Fri, 25 Jul 2008 10:48:29 +0000 (10:48 +0000)
org.glite.lb.server/Makefile
org.glite.lb.server/interface/lb_authz.h
org.glite.lb.server/src/bkserverd.c
org.glite.lb.server/src/db_store.c
org.glite.lb.server/src/lb_authz.c
org.glite.lb.server/src/lcas_lb.c [new file with mode: 0644]

index 17f0eca..2d80b0b 100644 (file)
@@ -177,6 +177,7 @@ ifeq ($(GLITE_LB_SERVER_WITH_WS),yes)
                ${LB_MACHINE_LIB} \
                ${LB_UTILS_DB_LIB} \
                ${GSOAP_LIB} \
+               -llcas \
                ${EXT_LIBS} \
                ${classadslib} \
                -lglite_lbu_maildir
@@ -189,6 +190,7 @@ else
                ${LB_MACHINE_LIB} \
                ${LB_UTILS_DB_LIB} \
                -lglite_security_gss_${nothrflavour} \
+               -llcas \
                ${EXT_LIBS} \
                ${classadslib} \
                -lglite_lbu_maildir
@@ -199,7 +201,7 @@ INDEX_OBJS:= index.o index_parse.o jobstat_supp.o openserver.o \
        lb_authz.o store.o bkindex.o stats.o\
        request.o db_store.o srv_purge.o notif_match.o il_lbproxy.o dump.o lb_xml_parse.o il_notification.o lb_proto.o lb_text.o server_state.o lb_xml_parse_V21.o lb_html.o notification.o seqcode.o userjobs.o load.o db_calls.o db_supp.lo
 
-INDEX_LIBS:= ${SRVBONES_LIB} ${COMMON_LIBS} ${LB_MACHINE_LIB} ${EXT_LIBS} ${LB_UTILS_DB_LIB}
+INDEX_LIBS:= ${SRVBONES_LIB} ${COMMON_LIBS} ${LB_MACHINE_LIB} ${EXT_LIBS} ${LB_UTILS_DB_LIB} -lcas
 
 WS_CLIENT_OBJS:= $(GSOAP_FILES_PREFIX)C.o $(GSOAP_FILES_PREFIX)Client.o ws_fault.o ws_typeref.o
 WS_CLIENT_LIBS:= ${GSOAP_LIB} -lglite_lb_common_${nothrflavour} \
@@ -230,6 +232,10 @@ LIB_OBJS_BK:= \
 MONDB_OBJS:=mon-db.o ${LIB_OBJS_BK}
 MONDB_LIBS:=${COMMON_LIBS} ${LB_MACHINE_LIB} ${LB_UTILS_DB_LIB} ${EXT_LIBS} 
 
+LCAS_PLUGIN_OBJS:=lcas_lb.o
+LCAS_PLUGIN_LOBJS:=${LCAS_PLUGIN_OBJS:.o=.lo}
+LCAS_PLUGIN_LIB:=liblcas_lb.la
+
 glite-lb-bkserverd: ${NSMAP} ${BKSERVER_OBJS}
        ${LINKXX} -o $@ ${BKSERVER_OBJS} ${BKSERVER_LIBS}
 
@@ -239,7 +245,7 @@ glite-lb-bkindex: ${INDEX_OBJS}
 glite-lb-mon-db: ${MONDB_OBJS}
        ${LINKXX} -o $@ ${MONDB_OBJS} ${MONDB_LIBS}
 
-compile: generate glite-lb-bkserverd glite-lb-bkindex glite-lb-mon-db ${STATIC_LIB_BK} ${MAN_GZ}
+compile: generate glite-lb-bkserverd glite-lb-bkindex glite-lb-mon-db ${STATIC_LIB_BK} ${LCAS_PLUGIN_LIB} ${MAN_GZ}
 
 generate: store.c index.c 
 
@@ -318,6 +324,9 @@ ${STATIC_LIB_BK}: ${LIB_OBJS_BK}
        ar crv $@ ${LIB_OBJS_BK}
        ranlib $@
 
+${LCAS_PLUGIN_LIB}: ${LCAS_PLUGIN_LOBJS}
+       ${LINK} -o $@ $<
+
 doc: ${MAN_GZ}
 
 man: ${MAN_GZ}
@@ -342,6 +351,9 @@ install:
        for p in bkserverd bkindex mon-db; do \
                ${INSTALL} -m 755 "glite-lb-$$p" "${PREFIX}/bin/glite-lb-$$p"; \
        done
+       -mkdir -p ${PREFIX}/lib/modules
+       ${INSTALL} -m 755 ${LCAS_PLUGIN_LOBJS} ${PREFIX}/lib/modules
+       ln -sf liblcas_lb.so ${PREFIX}/lib/modules/lcas_lb.mod
 
        for f in dbsetup.sql dbsetup-migrate2transactions.sql index.conf.template; do \
                ${INSTALL} -m 644 ${top_srcdir}/config/"glite-lb-$$f" ${PREFIX}/etc; \
index 3f8728f..a2f4149 100644 (file)
@@ -62,6 +62,9 @@ edg_wll_SetVomsGroups(edg_wll_Context, edg_wll_GssConnection *, char *, char *,
 extern void
 edg_wll_FreeVomsGroups(edg_wll_VomsGroups *);
 
+extern int
+check_store_authz(edg_wll_Context ctx, edg_wll_Event *ev);
+
 #ifdef __cplusplus
 }
 #endif
index 3cada5b..02ba9ae 100644 (file)
@@ -124,6 +124,7 @@ extern void _start (void), etext (void);
 
 
 
+int                                    enable_lcas = 0;
 int                                            debug  = 0;
 int                                            rgma_export = 0;
 static const int               one = 1;
@@ -171,6 +172,7 @@ static char *           port;
 
 
 static struct option opts[] = {
+        {"enable-lcas", 0, NULL,       'A'},
        {"cert",        1, NULL,        'c'},
        {"key",         1, NULL,        'k'},
        {"CAdir",       1, NULL,        'C'},
@@ -216,7 +218,7 @@ static struct option opts[] = {
        {NULL,0,NULL,0}
 };
 
-static const char *get_opt_string = "c:k:C:V:p:a:drm:ns:l:i:S:D:J:jR:F:xOL:N:X:Y:T:t:zb:gPBo:q:W:Z:"
+static const char *get_opt_string = "Ac:k:C:V:p:a:drm:ns:l:i:S:D:J:jR:F:xOL:N:X:Y:T:t:zb:gPBo:q:W:Z:"
 #ifdef GLITE_LB_SERVER_WITH_WS
        "w:"
 #endif
@@ -228,6 +230,7 @@ static const char *get_opt_string = "c:k:C:V:p:a:drm:ns:l:i:S:D:J:jR:F:xOL:N:X:Y
 static void usage(char *me) 
 {
        fprintf(stderr,"usage: %s [option]\n"
+               "\t-A, --enable-lcas\t activate LCAS-based authorization\n"
                "\t-a, --address\t use this server address (may be faked for debugging)\n"
                "\t-b, --transactions\t transactions switch (0, 1)\n"
                "\t-k, --key\t private key file\n"
@@ -404,6 +407,7 @@ int main(int argc, char *argv[])
        purge_timeout[EDG_WLL_JOB_CANCELLED] = 60*60*24*7;
 
        while ((opt = getopt_long(argc,argv,get_opt_string,opts,NULL)) != EOF) switch (opt) {
+               case 'A': enable_lcas = 1; break;
                case 'a': fake_host = strdup(optarg); break;
                case 'b': transactions = atoi(optarg); break;
                case 'c': server_cert = optarg; break;
index b6e402d..5ddf771 100644 (file)
@@ -24,6 +24,8 @@
 
 extern int unset_proxy_flag(edg_wll_Context, edg_wlc_JobId);
 extern int edg_wll_NotifMatch(edg_wll_Context, const edg_wll_JobStat *);
+extern int enable_lcas;
+
 
 static int db_store_finalize(edg_wll_Context ctx, char *event, edg_wll_Event *ev, edg_wll_JobStat *newstat, int reg_to_JP);
 
@@ -43,6 +45,9 @@ db_store(edg_wll_Context ctx, char *event)
 
   local_job = is_job_local(ctx, ev->any.jobId);
 
+  if (enable_lcas && check_store_authz(ctx, ev) != 0)
+    goto err;
+
 #ifdef LB_PERF
   if (sink_mode == GLITE_LB_SINK_STORE) {
          glite_wll_perftest_consumeEvent(ev);
index 651b123..1e748ec 100644 (file)
 #include "glite/jobid/cjobid.h"
 #include "glite/lbu/trio.h"
 #include "db_supp.h"
+#include <glite/security/lcas/lcas_pem.h>
 
 /* XXX should be defined in gridsite-gacl.h */
 GRSTgaclEntry *GACLparseEntry(xmlNodePtr cur);
 
+extern char *server_key;
+extern char *server_cert;
+
 static int 
 get_fqans(edg_wll_Context ctx, struct vomsdata *voms_info,
          char ***fqans)
@@ -839,6 +843,33 @@ end:
        return edg_wll_Error(ctx, NULL, NULL);
 }
 
+int
+check_store_authz(edg_wll_Context ctx, edg_wll_Event *ev)
+{
+   char *pem_string = NULL;
+   char *request = NULL;
+   int ret;
+
+   /* XXX make a real RSL ? */
+   request = edg_wll_EventToString(ev->any.type);
+   if (request == NULL)
+      return edg_wll_SetError(ctx, EINVAL, "Unknown event type");
+
+   ret = edg_wll_gss_get_client_pem(&ctx->connections->serverConnection->gss,
+                                   server_cert, server_key,
+                                    &pem_string);
+   if (ret)
+      return edg_wll_SetError(ctx, ret, "Failed to extract client's PEM string");
+
+   ret = lcas_pem(pem_string, request);
+   if (ret)
+      ret = edg_wll_SetError(ctx, EPERM, "Not allowed to log events here");
+
+   free(pem_string);
+
+   return ret;
+}
+
 #else /* VOMS & GACL */
 
 
diff --git a/org.glite.lb.server/src/lcas_lb.c b/org.glite.lb.server/src/lcas_lb.c
new file mode 100644 (file)
index 0000000..f216755
--- /dev/null
@@ -0,0 +1,167 @@
+#ident "$Header$"
+
+#include <glite/security/lcas/lcas_modules.h>
+
+static char *modname = "lcas_lb";
+static char *authfile = NULL;
+
+int
+plugin_initialize(int argc, char *argv[])
+{
+   int i;
+
+   lcas_log_debug(1, "%s-plugin_initialize(): passed arguments:\n",modname);
+   for (i=0; i < argc; i++)
+      lcas_log_debug(1, "\targ %d is %s\n", i,argv[i]);
+
+   if (argc > 1)
+      authfile = lcas_findfile(argv[1]);
+
+   if (authfile == NULL) {
+      lcas_log(0,"\t%s-plugin_initialize() error:"
+                 ":access control policy file required!\n",
+               modname);
+      return LCAS_MOD_NOFILE;
+   }
+
+   if (lcas_getfexist(1, authfile) == NULL) {
+      lcas_log(0, "\t%s-plugin_initialize() error:"
+                 "Cannot find access control policy file: %s\n",
+              modname, authfile);
+      return LCAS_MOD_NOFILE;
+   }
+
+   return LCAS_MOD_SUCCESS;
+}
+
+static char *
+get_event_name(lcas_request_t request)
+{
+   char *rsl = (char *) request;
+
+   if (request == NULL)
+      return NULL;
+
+   return strdup(rsl);
+}
+
+static int
+check_db_file(char *event, char *user_dn)
+{
+   FILE *db_file = NULL;
+   char line[1024];
+   int found = 0, inside_block = 0, found_event = 0;
+   char *p, *q;
+   int ret;
+
+   if (event == NULL || user_dn == NULL)
+      return LCAS_MOD_FAIL;
+
+   db_file = fopen(authfile, "r");
+   if (db_file == NULL) {
+      lcas_log_debug(1, "Failed to open policy file %s: %s\n",
+                     authfile, strerror(errno));
+      return LCAS_MOD_FAIL;
+   }
+
+   ret = LCAS_MOD_FAIL;
+   while (fgets(line, sizeof(line), db_file) != NULL) {
+      p = strchr(line, '\n');
+      if (p)
+         *p = '\0';
+      p = line;
+      if (*p == '#')
+         continue;
+
+      while (*p == ' ')
+         p++;
+
+      if (inside_block) {
+        q = strchr(p, '}');
+        if (q)
+           *q = '\0';
+        if (found_event && ((strcmp(p, user_dn) == 0) || *p == '*')) {
+           found = 1;
+           break;
+        }
+        if (q) {
+           inside_block = 0;
+        }
+      } else {
+        q = strchr(p, '=');
+        if (q == NULL)
+           continue;
+        *q = '\0';
+        inside_block = 1;
+        if (strncmp(p, event, strlen(event)) == 0 || *p == '*')
+           found_event = 1;
+      }
+   }
+   fclose(db_file);
+
+   if (found)
+      ret = LCAS_MOD_SUCCESS;
+
+   lcas_log_debug(1, "access %s\n",
+                  (ret == LCAS_MOD_SUCCESS) ? "granted" : "denied");
+
+   return ret;
+}
+
+int
+plugin_confirm_authorization(lcas_request_t request, lcas_cred_id_t lcas_cred)
+{
+   char *user_dn;
+   char *event = NULL;
+   int ret;
+
+   lcas_log_debug(1,"\t%s-plugin: checking LB access policy\n",
+                 modname);
+
+   event = get_event_name(request);
+   if (event == NULL) {
+      lcas_log_debug(1,"\t%s-plugin_confirm_authorization(): no event name specified\n",
+                     modname);
+      return LCAS_MOD_FAIL;
+   }
+
+   user_dn = lcas_get_dn(lcas_cred);
+   if (user_dn == NULL) {
+      lcas_log(0, "lcas.mod-lcas_get_fabric_authorization() error: user DN empty\n");
+      ret = LCAS_MOD_FAIL;
+      goto end;
+   }
+
+   ret = check_db_file(event, user_dn);
+
+end:
+   if (event)
+      free(event);
+
+   return ret; 
+}
+
+int
+plugin_terminate()
+{
+   lcas_log_debug(1, "%s-plugin_terminate(): terminating\n",modname);
+
+   if (authfile) {
+      free(authfile);
+      authfile = NULL;
+   }
+
+   return LCAS_MOD_SUCCESS;
+}
+
+#if 0
+int
+main(int argc, char *argv[])
+{
+   authfile = "lcas_lb.db";
+
+   check_db_file(argv[1], argv[2]);
+
+   return 0;
+}
+#endif