Support for anonymization of states
authorDaniel Kouřil <kouril@ics.muni.cz>
Sun, 22 Jan 2012 22:50:44 +0000 (22:50 +0000)
committerDaniel Kouřil <kouril@ics.muni.cz>
Sun, 22 Jan 2012 22:50:44 +0000 (22:50 +0000)
- a server-wide salt is used to make the hashes unique
- aggregation of the authz code; in the notification part it's been
  moved only before the message is actualy sent out
- a new authorization category (READ_ANONYMIZED) introduced

13 files changed:
org.glite.lb.server/Makefile
org.glite.lb.server/interface/lb_authz.h
org.glite.lb.server/src/authz_policy.c
org.glite.lb.server/src/authz_policy.h
org.glite.lb.server/src/crypto.c [new file with mode: 0644]
org.glite.lb.server/src/crypto.h [new file with mode: 0644]
org.glite.lb.server/src/il_notification.c
org.glite.lb.server/src/il_notification.h
org.glite.lb.server/src/jobstat.c
org.glite.lb.server/src/lb_authz.c
org.glite.lb.server/src/notif_match.c
org.glite.lb.server/src/notification.c
org.glite.lb.server/src/server_state.h

index c9f9885..c87d4de 100644 (file)
@@ -170,7 +170,7 @@ BKSERVER_BASE_OBJS:= \
        openserver.o query.o userjobs.o db_store.o request.o store.o \
        stored_master.o srv_purge.o server_state.o dump.o lb_authz.o load.o \
        notification.o il_notification.o notif_match.o stats.o db_calls.o db_supp.o lb_rss.o pretty_print_wrapper.o \
-       policy_gram.o policy_lex.o authz_policy.o
+       policy_gram.o policy_lex.o authz_policy.o crypto.o
 
 gsoap_version ?= ${gsoap_default_version}
 
@@ -214,7 +214,7 @@ endif
 INDEX_OBJS:= index.o index_parse.o jobstat_supp.o openserver.o \
        jobstat.o query.o get_events.o write2rgma.o index_lex.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 cond_dump.o notification.o seqcode.o userjobs.o load.o db_calls.o db_supp.o lb_rss.o pretty_print_wrapper.o authz_policy.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 cond_dump.o notification.o seqcode.o userjobs.o load.o db_calls.o db_supp.o lb_rss.o pretty_print_wrapper.o authz_policy.o crypto.o
 
 INDEX_LIBS:= ${SRVBONES_LIB} ${COMMON_LIBS} ${LB_MACHINE_LIB} ${EXT_LIBS} ${LB_UTILS_DB_LIB}
 
@@ -234,7 +234,8 @@ LIB_OBJS_BK:= \
        openserver.o query.o userjobs.o db_store.o request.o store.o \
        stored_master.o srv_purge.o server_state.o dump.o lb_authz.o load.o \
        notification.o il_notification.o notif_match.o stats.o write2rgma.o \
-       db_calls.o db_supp.o lb_rss.o pretty_print_wrapper.o authz_policy.o
+       db_calls.o db_supp.o lb_rss.o pretty_print_wrapper.o authz_policy.o \
+       crypto.o
 
 MONDB_OBJS:=mon-db.o ${LIB_OBJS_BK}
 MONDB_LIBS:=${COMMON_LIBS} ${LB_MACHINE_LIB} ${LB_UTILS_DB_LIB} ${EXT_LIBS}
index 9295d0c..8da9f42 100644 (file)
@@ -97,6 +97,14 @@ edg_wll_get_fqans(edg_wll_Context ctx, struct vomsdata *voms_info,
 int
 edg_wll_acl_print(edg_wll_Context ctx, edg_wll_Acl a, char **policy);
 
+int
+check_jobstat_authz(edg_wll_Context ctx,
+                    const edg_wll_JobStat *stat,
+                    int job_flags,
+                    edg_wll_Acl acl,
+                    struct _edg_wll_GssPrincipal_data *peer,
+                    int *authz_flags);
+
 #ifdef __cplusplus
 }
 #endif
index 0343cbb..16c7d2a 100644 (file)
@@ -17,11 +17,14 @@ limitations under the License.
 
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
 
 #include <cclassad.h>
 
 #include <glite/security/glite_gss.h>
 #include "authz_policy.h"
+#include "server_state.h"
+#include "crypto.h"
 
 struct action_name action_names[] = {
     { ADMIN_ACCESS,    "ADMIN_ACCESS" },
@@ -34,6 +37,7 @@ struct action_name action_names[] = {
     { READ_ALL, "READ_ALL" },
     { PURGE, "PURGE" },
     { GRANT_OWNERSHIP, "GRANT_OWNERSHIP" },
+    { READ_ANONYMIZED, "READ_ANONYMIZED" },
 };
 
 static int num_actions =
@@ -201,3 +205,47 @@ blacken_fields(edg_wll_JobStat *stat, int flags)
     edg_wll_FreeStatus(&new_stat);
     return 0;
 }
+
+int
+anonymize_stat(edg_wll_Context ctx, edg_wll_JobStat *stat)
+{
+    char *salt = NULL, *hash;
+    int ret;
+
+    ret = edg_wll_GetServerState(ctx, EDG_WLL_STATE_ANONYMIZATION_SALT, &salt);
+    switch (ret) {
+       case ENOENT:
+           edg_wll_ResetError(ctx);
+           ret = generate_salt(ctx, &salt);
+           if (ret)
+               break;
+           ret = edg_wll_SetServerState(ctx, EDG_WLL_STATE_ANONYMIZATION_SALT, salt);
+           break;
+       default:
+           break;
+    }
+    if (ret)
+       goto end;
+
+    ret = sha256_salt(ctx, stat->owner, salt, &hash);
+    if (ret)
+       goto end;
+    free(stat->owner);
+    stat->owner = hash;
+
+    if (stat->payload_owner) {
+       ret = sha256_salt(ctx, stat->payload_owner, salt, &hash);
+       if (ret)
+           goto end;
+       free(stat->payload_owner);
+       stat->payload_owner = hash;
+    }
+
+    ret = 0;
+
+end:
+    if (salt)
+       free(salt);
+    
+    return ret;
+}
index 2f93e92..c1b035d 100644 (file)
@@ -34,6 +34,7 @@ typedef enum {
     READ_ALL           = 1 << 7,
     PURGE              = 1 << 8,
     GRANT_OWNERSHIP    = 1 << 9,
+    READ_ANONYMIZED    = 1 << 10,
 } authz_action;
 
 typedef struct action_name {
@@ -70,4 +71,7 @@ find_authz_attr(const char *name);
 int
 blacken_fields(edg_wll_JobStat *, int flags);
 
+int
+anonymize_stat(edg_wll_Context, edg_wll_JobStat *);
+
 #endif
diff --git a/org.glite.lb.server/src/crypto.c b/org.glite.lb.server/src/crypto.c
new file mode 100644 (file)
index 0000000..34d2cc7
--- /dev/null
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <openssl/sha.h>
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+
+#include <glite/lbu/log.h>
+#include <glite/lb/context-int.h>
+
+#include "crypto.h"
+
+int
+sha256_salt(edg_wll_Context ctx, const char *string,
+           const char *salt, char **hash)
+{
+    SHA256_CTX context;
+    unsigned char md[SHA256_DIGEST_LENGTH];
+    char output[SHA256_DIGEST_LENGTH+1];
+    char *input;
+    int ret, i;
+
+    SSL_library_init();
+    OpenSSL_add_all_algorithms();
+
+    ret = asprintf(&input, "%s%s", string, salt);
+    if (ret < 0)
+       return edg_wll_SetError(ctx, ENOMEM, "Computing hash");
+
+    SHA256_Init(&context);
+    SHA256_Update(&context, input, strlen(input));
+    SHA256_Final(md, &context);
+    free(input);
+
+    for (i=0; i < SHA256_DIGEST_LENGTH; i++)
+       sprintf(output + i*2, "%02x", md[i]);
+    output[SHA256_DIGEST_LENGTH*2] = '\0';
+
+    *hash = strdup(output);
+    if (*hash == NULL)
+       return edg_wll_SetError(ctx, ENOMEM, "Computing hash");
+
+    return 0;
+}
+
+int
+generate_salt(edg_wll_Context ctx, char **new_salt)
+{
+    int ret, i;
+    unsigned char rand_bytes[16];
+    char salt[sizeof(rand_bytes)*2 + 1];
+
+    ret = RAND_bytes(rand_bytes, sizeof(rand_bytes));
+    if (ret != 1) {
+       glite_common_log_msg(LOG_CATEGORY_LB_SERVER, LOG_PRIORITY_ERROR,
+               "Failed to generate random seed");
+       return edg_wll_SetError(ctx,EINVAL,"Anonymization failed");
+    }
+
+    for (i = 0; i < sizeof(rand_bytes); i++)
+       sprintf(salt + i*2, "%02x", rand_bytes[i]);
+    salt[sizeof(salt) - 1] = '\0';
+    *new_salt = strdup(salt);
+    if (*new_salt == NULL)
+       return edg_wll_SetError(ctx,ENOMEM,NULL);
+
+    return 0;
+}
diff --git a/org.glite.lb.server/src/crypto.h b/org.glite.lb.server/src/crypto.h
new file mode 100644 (file)
index 0000000..c4f16b9
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef GLITE_LB_CRYPTO_H
+#define GLITE_LB_CRYPTO_H
+
+#include <glite/lb/context.h>
+
+int
+sha256_salt(edg_wll_Context ctx, const char *string,
+           const char *salt, char **hash);
+
+int
+generate_salt(edg_wll_Context ctx, char **new_salt);
+
+#endif
index 5995c95..fc82346 100644 (file)
@@ -187,7 +187,6 @@ edg_wll_NotifJobStatus(edg_wll_Context      context,
                       const char      *dest_url,
                       const char      *owner,
                        int             flags,
-                      int              authz_flags,
                       int              expires,
                       const edg_wll_JobStat notif_job_stat)
 {
@@ -202,9 +201,18 @@ edg_wll_NotifJobStatus(edg_wll_Context     context,
                stat.condor_jdl = NULL;
                stat.rsl = NULL;
        }
-       if (authz_flags)
-               blacken_fields(&stat, authz_flags);
 
+       ret = edg_wll_NotifCheckAuthz(context, &stat, flags, owner);
+       if (ret != 1) {
+               char *ju;
+               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_INFO,
+                                "[%d] authorization failed when sending notification for job %s",
+                                getpid(),
+                                ju = glite_jobid_getUnique(stat.jobId));
+               free(ju);
+               return edg_wll_SetError(context, EPERM, NULL);
+       }
+               
        if(edg_wll_JobStatusToXML(context, stat, &xml_data)) 
                goto out;
        
index 5490193..4afe090 100644 (file)
@@ -84,7 +84,6 @@ edg_wll_NotifJobStatus(edg_wll_Context        context,
                       const char      *dest_url,
                       const char      *owner,
                        int              flags,
-                      int              authz_flags,
                       int              expires,
                       const edg_wll_JobStat notif_job_stat);
 
@@ -120,7 +119,7 @@ int edg_wll_NotifMatch(edg_wll_Context context, const edg_wll_JobStat *oldstat,
 /**
  * Check permissions on job status.
  */
-int edg_wll_NotifCheckACL(edg_wll_Context ctx,const edg_wll_JobStat *stat,const char *recip, int *authz_flags);
+int edg_wll_NotifCheckAuthz(edg_wll_Context ctx,edg_wll_JobStat *stat,int flags,const char *recip);
 
 #ifdef __cplusplus
 }
index 1f01e6a..13c5c70 100644 (file)
@@ -89,38 +89,6 @@ static char* matched_substr(char *in, regmatch_t match)
        return s;
 }
 
-static int
-check_jobstat_authz(edg_wll_Context ctx,
-       edg_wll_JobStat *stat,
-       edg_wll_Acl acl,
-       int *flags)
-{
-       struct _edg_wll_GssPrincipal_data princ;
-
-       *flags = 0;
-
-       if (ctx->noAuth)
-               return 1;
-       if (ctx->peerName == NULL)
-               return 0;
-       if (edg_wll_gss_equal_subj(ctx->peerName, stat->owner))
-               return 1;
-       if (stat->payload_owner && edg_wll_gss_equal_subj(ctx->peerName, stat->payload_owner))
-               return 1;
-       if (acl && edg_wll_CheckACL(ctx, acl, EDG_WLL_CHANGEACL_READ) == 0)
-               return 1;
-       edg_wll_ResetError(ctx);
-       princ.name = ctx->peerName;
-       princ.fqans = ctx->fqans;
-       if (check_authz_policy(&ctx->authz_policy, &princ, READ_ALL))
-               return 1;
-       if (check_authz_policy(&ctx->authz_policy, &princ, STATUS_FOR_MONITORING)) {
-               *flags |= STATUS_FOR_MONITORING;
-               return 1;
-       }
-       return 0;
-}
-
 int edg_wll_JobStatusServer(
        edg_wll_Context ctx,
        glite_jobid_const_t             job,
@@ -145,7 +113,7 @@ int edg_wll_JobStatusServer(
        glite_lbu_Statement sh = NULL;
        int num_sub, num_f, i, ii;
        int authz_flags = 0;
-
+       struct _edg_wll_GssPrincipal_data peer;
 
        edg_wll_ResetError(ctx);
 
@@ -175,7 +143,11 @@ int edg_wll_JobStatusServer(
                
                if (edg_wll_GetACL(ctx, job, &acl)) goto rollback;
 
-               if (check_jobstat_authz(ctx, stat, acl, &authz_flags) == 0) {
+               
+               memset(&peer, 0, sizeof(peer));
+               peer.name = ctx->peerName;
+               peer.fqans = ctx->fqans;
+               if (check_jobstat_authz(ctx, stat, flags, acl, &peer, &authz_flags) == 0) {
                        edg_wll_SetError(ctx, EPERM, "not owner");
                        goto rollback;
                }
@@ -425,9 +397,12 @@ rollback:
        free(string_jobid);
        free(md5_jobid);
 
-       if (authz_flags)
+       if (authz_flags & STATUS_FOR_MONITORING)
                blacken_fields(stat, authz_flags);
 
+       if (authz_flags & READ_ANONYMIZED)
+               anonymize_stat(ctx, stat);
+
        return edg_wll_Error(ctx, NULL, NULL);
 }
 
index b6130e2..6cc9981 100644 (file)
@@ -1170,3 +1170,42 @@ end:
 
     return ret;
 }
+
+int
+check_jobstat_authz(edg_wll_Context ctx,
+                   const edg_wll_JobStat *stat,
+                   int job_flags,
+                   edg_wll_Acl acl,
+                   struct _edg_wll_GssPrincipal_data *peer,
+                   int *authz_flags)
+{
+    *authz_flags = 0;
+
+    if (peer == NULL || peer->name == NULL)
+       return 0;
+
+    if (edg_wll_gss_equal_subj(peer->name, stat->owner))
+       return 1;
+    if (stat->payload_owner && edg_wll_gss_equal_subj(peer->name, stat->payload_owner))
+       return 1;
+
+    if (job_flags & EDG_WLL_NOTIF_HISTORY ||
+       check_authz_policy(&ctx->authz_policy, peer, READ_ANONYMIZED))
+       *authz_flags |= READ_ANONYMIZED;
+
+    if (ctx->noAuth ||
+       edg_wll_amIroot(peer->name, peer->fqans, &ctx->authz_policy))
+       return 1;
+    if (acl && edg_wll_CheckACL_princ(ctx, acl, EDG_WLL_CHANGEACL_READ, peer) == 0)
+       return 1;
+    edg_wll_ResetError(ctx);
+
+    if (check_authz_policy(&ctx->authz_policy, peer, READ_ALL))
+       return 1;
+    if (check_authz_policy(&ctx->authz_policy, peer, STATUS_FOR_MONITORING)) {
+       *authz_flags |= STATUS_FOR_MONITORING;
+       return 1;
+    }
+
+    return 0;
+}
index da19988..b99820e 100644 (file)
@@ -49,7 +49,7 @@ int edg_wll_NotifMatch(edg_wll_Context ctx, const edg_wll_JobStat *oldstat, cons
        edg_wll_NotifId         nid = NULL;
        char    *jobq,*ju = NULL,*jobc[6];
        glite_lbu_Statement     jobs = NULL;
-       int     ret,flags,authz_flags = 0;
+       int     ret,flags;
        size_t i;
        time_t  expires,now = time(NULL);
        
@@ -121,8 +121,7 @@ int edg_wll_NotifMatch(edg_wll_Context ctx, const edg_wll_JobStat *oldstat, cons
                        glite_common_log(LOG_CATEGORY_LB_SERVER, LOG_PRIORITY_DEBUG, "[%d] NOTIFY:%s expired at %s UTC", 
                                getpid(),jobc[0],asctime(gmtime(&expires)));
                }
-               else if (notif_match_conditions(ctx,oldstat,&newstat,jobc[4],flags) &&
-                               edg_wll_NotifCheckACL(ctx,&newstat,jobc[3], &authz_flags))
+               else if (notif_match_conditions(ctx,oldstat,&newstat,jobc[4],flags))
                {
                        char    *errt, *errd;
                        char    *dest;
@@ -152,7 +151,7 @@ int edg_wll_NotifMatch(edg_wll_Context ctx, const edg_wll_JobStat *oldstat, cons
                        /* XXX: only temporary hack!!!
                         */
                        ctx->p_instance = strdup("");
-                       if ( edg_wll_NotifJobStatus(ctx, nid, dest, jobc[3], atoi(jobc[5]), authz_flags, expires, newstat) )
+                       if ( edg_wll_NotifJobStatus(ctx, nid, dest, jobc[3], atoi(jobc[5]), expires, newstat) )
                        {
                                for (i=0; i<sizeof(jobc)/sizeof(jobc[0]); i++) free(jobc[i]);
                                goto err;
@@ -234,48 +233,38 @@ static int notif_match_conditions(edg_wll_Context ctx,const edg_wll_JobStat *old
  * effective VOMS groups of the recipient are not available here, should be 
  * probably stored along with the registration.
  */
-int edg_wll_NotifCheckACL(edg_wll_Context ctx,const edg_wll_JobStat *stat,const char *recip, int *authz_flags)
+int edg_wll_NotifCheckAuthz(edg_wll_Context ctx,edg_wll_JobStat *stat,
+                           int flags,const char *recip)
 {
        int             ret;
        struct _edg_wll_GssPrincipal_data princ;
        edg_wll_Acl     acl = NULL;
+       int             authz_flags = 0;
 
        memset(&princ, 0, sizeof(princ));
-       *authz_flags = 0;
-
-       edg_wll_ResetError(ctx);
-       if (strcmp(stat->owner,recip) == 0
-               || edg_wll_amIroot(recip,NULL,&ctx->authz_policy)) return 1;
-       if (stat->payload_owner && strcmp(stat->payload_owner,recip) == 0)
-               return 1;
        princ.name = (char *)recip;
-       if (check_authz_policy(&ctx->authz_policy, &princ, READ_ALL))
-               return 1;
 
        if (stat->acl) {
                acl =  calloc(1,sizeof *acl);
                ret = edg_wll_DecodeACL(stat->acl,&acl->value);
                if (ret) {
-                       edg_wll_FreeAcl(acl);
-                       edg_wll_SetError(ctx,EINVAL,"decoding ACL");
-                       return 0;
+                       free(acl);
+                       acl = NULL;
                }
+       }
 
-               acl->string = stat->acl; 
-               ret = edg_wll_CheckACL(ctx, acl, EDG_WLL_CHANGEACL_READ);
-               acl->string = NULL;
+       ret = check_jobstat_authz(ctx, stat, flags, acl, &princ, &authz_flags);
+       if (acl)
                edg_wll_FreeAcl(acl);
-               if (ret == 0)
-                       return 1;
-               edg_wll_ResetError(ctx);
-       }
+       if (ret != 1)
+               return ret;
 
-       if (check_authz_policy(&ctx->authz_policy, &princ, STATUS_FOR_MONITORING)) {
-               *authz_flags |= STATUS_FOR_MONITORING;
-                return 1;
-       }
+       if (authz_flags & STATUS_FOR_MONITORING)
+               blacken_fields(stat, authz_flags);
+       if (authz_flags & READ_ANONYMIZED)
+               anonymize_stat(ctx, stat);
 
-       return 0;
+       return ret;
 }
 
 
index 21e5236..299b35a 100644 (file)
@@ -1001,7 +1001,6 @@ static int notif_streaming_event_cb(edg_wll_Context ctx, glite_jobid_t jobid, ed
        const char *owner;
        int flags;
        time_t expire;
-       int authz_flags;
        size_t i;
        char *ju;
        char *row[4] = {};
@@ -1023,19 +1022,12 @@ static int notif_streaming_event_cb(edg_wll_Context ctx, glite_jobid_t jobid, ed
        flags = atoi(row[2]);
        owner = row[3];
 
-       if (!edg_wll_NotifCheckACL(ctx, (const edg_wll_JobStat *)stat, owner, &authz_flags)) {
-               glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_INFO, "[%d] NOTIFY stream: %s, authorization failed, job %s", getpid(), lctx->nid_s, ju = glite_jobid_getUnique(stat->jobId));
-               free(ju); ju = NULL;
-               edg_wll_ResetError(ctx);
-               goto cleanup;
-       }
-
        glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_INFO, "[%d] NOTIFY stream: %s, job %s, destination '%s'", getpid(), lctx->nid_s, ju = glite_jobid_getUnique(stat->jobId), row[0]);
        free(ju); ju = NULL;
 
        dest = strdup(row[0]);
        /*XXX: ??? copied from notif_match.c */ free(ctx->p_instance); ctx->p_instance = strdup("");
-       if (edg_wll_NotifJobStatus(ctx, lctx->nid, dest, owner, flags, authz_flags, expire, (const edg_wll_JobStat)(*stat)) != 0) {
+       if (edg_wll_NotifJobStatus(ctx, lctx->nid, dest, owner, flags, expire, (const edg_wll_JobStat)(*stat)) != 0) {
                glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_ERROR, "[%d] NOTIFY stream: %s, error", getpid(), lctx->nid_s);
                goto cleanup;
        }
index 25b3db1..d50b342 100644 (file)
@@ -22,6 +22,7 @@ limitations under the License.
 
 #define EDG_WLL_STATE_DUMP_START       "StartDump"
 #define EDG_WLL_STATE_DUMP_END         "EndDump"
+#define EDG_WLL_STATE_ANONYMIZATION_SALT       "AnonymizationSalt"
 
 int edg_wll_GetServerState(edg_wll_Context,const char *,char **);
 int edg_wll_SetServerState(edg_wll_Context,const char *,const char *);