--- /dev/null
+#include <stdlib.h>
+#include <string.h>
+
+#include <glite/security/glite_gss.h>
+#include "authz_policy.h"
+
+struct action_name action_names[] = {
+ { READ_ALL, "READ_ALL" },
+ { READ_RTM, "READ_RTM" },
+};
+
+static int num_actions =
+ sizeof(action_names) / sizeof(action_names[0]);
+
+struct attr_id_name attr_id_names[] = {
+ { ATTR_SUBJECT, "subject" },
+ { ATTR_FQAN, "fqan" },
+};
+
+static int num_attrs =
+ sizeof(attr_id_names) / sizeof(attr_id_names[0]);
+
+
+int
+check_authz_policy(edg_wll_Context ctx, edg_wll_authz_policy policy,
+ authz_action action)
+{
+ int i;
+ char **f;
+ _edg_wll_authz_rule *r;
+
+ if (policy == NULL)
+ return 0;
+
+ for (i = 0; i < policy->num; i++) {
+ r = policy->rules + i;
+ if (r->action != action)
+ break;
+ switch (r->attr_id) {
+ case ATTR_SUBJECT:
+ if (edg_wll_gss_equal_subj(r->attr_value, ctx->peerName))
+ return 1;
+ break;
+ case ATTR_FQAN:
+ for (f = ctx->fqans; f && *f; f++)
+ if (strcmp(r->attr_value, *f) == 0)
+ return 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+authz_action
+find_authz_action(const char *name)
+{
+ int i;
+
+ for (i = 0; i < num_actions; i++)
+ if (strcmp(action_names[i].name, name) == 0)
+ return action_names[i].action;
+ return ACTION_UNDEF;
+}
+
+authz_attr_id
+find_authz_attr(const char *name)
+{
+ int i;
+
+ for (i = 0; i < num_attrs; i++)
+ if (strcmp(attr_id_names[i].name, name) == 0)
+ return attr_id_names[i].id;
+ return ATTR_UNDEF;
+}
--- /dev/null
+#ifndef GLITE_LB_AUTHZ_POLICY_H
+#define GLITE_LB_AUTHZ_POLICY_H
+
+#include <glite/lb/context-int.h>
+#include <glite/lb/authz.h>
+
+typedef enum {
+ ACTION_UNDEF = 0,
+ READ_ALL = 2,
+ READ_RTM = 4,
+} authz_action;
+
+typedef struct action_name {
+ authz_action action;
+ const char *name;
+} action_name;
+
+typedef enum {
+ ATTR_UNDEF = 0,
+ ATTR_SUBJECT = 2,
+ ATTR_FQAN = 4,
+} authz_attr_id;
+
+struct attr_id_name {
+ authz_attr_id id;
+ const char *name;
+} attr_id_name;
+
+int
+parse_server_policy(edg_wll_Context ctx, const char *filename, edg_wll_authz_policy policy);
+
+int
+check_authz_policy(edg_wll_Context, edg_wll_authz_policy, authz_action);
+
+authz_action
+find_authz_action(const char *name);
+
+authz_attr_id
+find_authz_attr(const char *name);
+
+#endif
#include "db_calls.h"
#include "db_supp.h"
#include "openserver.h"
+#include "authz_policy.h"
#ifdef GLITE_LB_SERVER_WITH_WS
# if GSOAP_VERSION < 20700
static char host[300];
static char * port;
static time_t rss_time = 60*60;
+static char * policy_file = NULL;
+struct _edg_wll_authz_policy authz_policy = { NULL, 0};
{"proxy-il-fprefix", 1, NULL, 'Z'},
{"proxy-purge", 0, NULL, 'G'},
{"rss-time", 1, NULL, 'I'},
+ {"policy", 1, NULL, 'l'},
{NULL,0,NULL,0}
};
-static const char *get_opt_string = "Ac:k:C:V:p:a:drm:ns:i:S:D:J:jR:F:xOL:N:X:Y:T:t:zb:gPBo:q:W:Z:GI:"
+static const char *get_opt_string = "Ac:k:C:V:p:a:drm:ns:i:S:D:J:jR:F:xOL:N:X:Y:T:t:zb:gPBo:q:W:Z:GI:l:"
#ifdef GLITE_LB_SERVER_WITH_WS
"w:"
#endif
"\t-W,--proxy-il-sock\t socket to send events to\n"
"\t-Z,--proxy-il-fprefix\t file prefix for events\n"
"\t-G,--proxy-purge\t enable automatic purge on proxy service (disabled by default)\n"
- "\t-I,--rss-time age\t (in seconds) of job states published via RSS\n"
+ "\t-I,--rss-time\t age (in seconds) of job states published via RSS\n"
+ "\t-l,--policy\tauthorization policy file\n"
,me);
}
break;
case 'I': rss_time = atol(optarg);
break;
+ case 'l': policy_file = strdup(optarg);
+ break;
case '?': usage(name); return 1;
}
if (fprintf(fpid, "%d", getpid()) <= 0) { perror(pidfile); return 1; }
if (fclose(fpid) != 0) { perror(pidfile); return 1; }
+ if (policy_file && parse_server_policy(ctx, policy_file, &authz_policy)) {
+ char *et, *ed;
+
+ edg_wll_Error(ctx,&et,&ed);
+ glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "Cannot load server policy: %s: %s\n", et, ed);
+ return 1;
+ }
+
+
if (mode & SERVICE_SERVER) {
if (check_mkdir(dumpStorage)){
glite_common_log(LOG_CATEGORY_CONTROL, LOG_PRIORITY_FATAL, "Directory for dump files not redy!");
ctx->hardJobsLimit = hardJobsLimit;
ctx->hardEventsLimit = hardEventsLimit;
if ( noAuth ) ctx->noAuth = 1;
+ if ( authz_policy.num ) {
+ int i;
+ for (i=0; i < authz_policy.num; i++)
+ edg_wll_add_authz_rule(ctx, &ctx->authz_policy,
+ (authz_policy.rules[i]).action,
+ (authz_policy.rules[i]).attr_id,
+ (authz_policy.rules[i]).attr_value);
+ }
ctx->rgma_export = rgma_export;
memcpy(ctx->purge_timeout, purge_timeout, sizeof(ctx->purge_timeout));
#include "stats.h"
#include "db_supp.h"
#include "db_calls.h"
+#include "authz_policy.h"
#define DAG_ENABLE 1
return s;
}
+static int
+check_jobstat_authz(edg_wll_Context ctx,
+ char *owner,
+ edg_wll_Acl acl,
+ int *flags)
+{
+ *flags = 0;
+ if (ctx->noAuth)
+ return 1;
+ if (ctx->peerName && edg_wll_gss_equal_subj(ctx->peerName, owner))
+ return 1;
+ if (acl && edg_wll_CheckACL(ctx, acl, EDG_WLL_CHANGEACL_READ) == 0)
+ return 1;
+ edg_wll_ResetError(ctx);
+ if (check_authz_policy(ctx, &ctx->authz_policy, READ_RTM)) {
+ *flags |= READ_RTM;
+ return 1;
+ }
+ return 0;
+}
int edg_wll_JobStatusServer(
edg_wll_Context ctx,
char *out[1], *out_stat[3];
glite_lbu_Statement sh = NULL;
int num_sub, num_f, i, ii;
+ int authz_flags = 0;
edg_wll_ResetError(ctx);
if (edg_wll_GetACL(ctx, job, &acl)) goto rollback;
- /* authorization check */
- if ( !(ctx->noAuth) &&
- (!(ctx->peerName) || !edg_wll_gss_equal_subj(ctx->peerName, stat->owner))) {
- if ((acl == NULL) || edg_wll_CheckACL(ctx, acl, EDG_WLL_CHANGEACL_READ)) {
- if (acl) {
- goto rollback;
- } else {
- edg_wll_SetError(ctx,EPERM, "not owner, no ACL is set");
- goto rollback;
- }
- }
+ if (check_jobstat_authz(ctx, stat->owner, acl, &authz_flags) == 0) {
+ edg_wll_SetError(ctx, EPERM, "not owner");
+ goto rollback;
}
-
+
if (acl) {
stat->acl = strdup(acl->string);
edg_wll_FreeAcl(acl);
free(string_jobid);
free(md5_jobid);
+ if (authz_flags && authz_flags & READ_RTM) {
+ edg_wll_JobStat new_stat;
+
+ memset(&new_stat, 0, sizeof(new_stat));
+ new_stat.state = stat->state;
+ /* XXX save anything else */
+
+ edg_wll_FreeStatus(stat);
+ memset(stat, 0, sizeof(*stat));
+ edg_wll_CpyStatus(&new_stat, stat);
+ }
+
return edg_wll_Error(ctx, NULL, NULL);
}
--- /dev/null
+%{
+
+#ident "$Header$"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "glite/lb/context-int.h"
+#include "authz_policy.h"
+
+void yyerror (const char *);
+void set_error(const char *format, ...);
+
+static edg_wll_Context parse_ctx;
+static const char *parse_fname;
+static edg_wll_authz_policy parse_policy;
+
+extern unsigned lineno;
+
+extern FILE *yyin;
+
+struct _assigs {
+ int id;
+ char *value;
+ struct _assigs *next;
+} _assigs;
+
+struct _assigs *assigs = NULL;
+
+%}
+
+%union {
+ char *string;
+ struct _assigs *assigs;
+}
+
+%token RESOURCE ACTION RULE PERMIT
+%token <string> STRING
+%token <string> LITERAL
+%type <assigs> assignment assignments
+
+%start policy
+
+%%
+
+policy : RESOURCE STRING '{' actions '}'
+ {
+ if (strcmp($2, "LB") != 0)
+ set_error("Undefined resource '%s'", $2);
+ }
+ ;
+
+actions :
+ | action actions
+ ;
+
+action : ACTION STRING '{' rules '}'
+ {
+ struct _assigs *a;
+ authz_action ac = find_authz_action($2);
+
+ if (ac == ACTION_UNDEF)
+ set_error("undefined action '%s'", $2);
+
+ for (a = assigs; a; a = a->next) {
+ edg_wll_add_authz_rule(parse_ctx, parse_policy,
+ ac, a->id, a->value);
+ }
+ assigs = NULL; /* XXX */
+ }
+ ;
+
+rules :
+ | rule rules
+ ;
+
+rule : RULE PERMIT '{' assignments '}'
+ {
+ assigs = $4;
+ }
+ ;
+
+assignments : assignment assignments
+ {
+ $1->next = $2;
+ $$ = $1;
+ }
+ | assignment
+ ;
+
+assignment : LITERAL '=' STRING
+ {
+ $$ = malloc(sizeof(*$$));
+ $$->id = find_authz_attr($1);
+ if ($$->id == ATTR_UNDEF)
+ set_error("undefined attribute '%s'", $1);
+ $$->value = $3;
+ $$->next = NULL;
+ }
+ ;
+
+%%
+
+void set_error(const char *format, ...)
+{
+ va_list args;
+ char *buf, *msg;
+
+ va_start (args, format);
+ vasprintf (&buf, format, args);
+ va_end(args);
+
+ asprintf(&msg, "%s:%d: %s", parse_fname, lineno, buf);
+ edg_wll_SetError(parse_ctx, EINVAL, msg);
+ free(buf);
+ free(msg);
+}
+
+void yyerror(const char *str)
+{
+ set_error("%s", str);
+}
+
+int
+parse_server_policy(edg_wll_Context ctx, const char *filename, edg_wll_authz_policy policy)
+{
+ lineno = 1;
+ yyin = fopen(filename, "r");
+ if (yyin == NULL)
+ return edg_wll_SetError(ctx,errno,filename);
+
+ parse_ctx = ctx;
+ parse_fname = filename;
+ parse_policy = policy;
+ edg_wll_ResetError(ctx);
+ yyparse();
+ fclose(yyin);
+
+ return edg_wll_Error(ctx,NULL,NULL);
+}
--- /dev/null
+%{
+
+#ident "$Header$"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include "policy_gram.h"
+
+unsigned lineno = 1;
+
+#define YY_NO_UNPUT
+
+%}
+%%
+
+resource { return RESOURCE; }
+action { return ACTION; }
+rule { return RULE; }
+permit { return PERMIT; }
+[A-Za-z0-9_]+ {
+ yylval.string = strdup ((const char *)yytext);
+ return LITERAL;
+ }
+\"[^\"\n]*\" {
+ int len;
+ yylval.string = malloc(len = strlen(yytext)-1);
+ strncpy(yylval.string,yytext+1,len-1);
+ yylval.string[len-1] = '\0';
+ return STRING;
+ }
+[={}] { return *yytext; }
+"\n" { lineno++; }
+[ \t]+ ;
+. { return *yytext; }
+%%
+
+int yywrap() { return 1; }