static int do_eval(struct filter_env *env, struct filter_tree *t, struct filter_tree *res) { int c; struct filter_tree r1, r2; int lang_id, prob_id, user_id, flags; const struct userlist_user *u; const struct userlist_member *m; const unsigned char *s; memset(res, 0, sizeof(*res)); switch (t->kind) { case TOK_LOGOR: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_BOOL_L); if (!r1.v.b) { if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_BOOL_L); res->v.b = r2.v.b; } else { res->v.b = 1; } break; case TOK_LOGAND: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_BOOL_L); if (r1.v.b) { if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_BOOL_L); res->v.b = r2.v.b; } else { res->v.b = 0; } break; /* binary */ case '^': case '|': case '&': case '*': case '/': case '%': case '+': case '-': case '>': case '<': case TOK_EQ: case TOK_NE: case TOK_LE: case TOK_GE: case TOK_ASL: case TOK_ASR: case TOK_REGEXP: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, &r2); /* unary */ case '~': case '!': case TOK_UN_MINUS: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0); case TOK_TIME: case TOK_DUR: case TOK_SIZE: case TOK_HASH: case TOK_UUID: case TOK_IP: case TOK_PROB: case TOK_UID: case TOK_LOGIN: case TOK_NAME: case TOK_GROUP: case TOK_LANG: case TOK_ARCH: case TOK_RESULT: case TOK_SCORE: case TOK_TEST: case TOK_IMPORTED: case TOK_HIDDEN: case TOK_READONLY: case TOK_MARKED: case TOK_SAVED: case TOK_VARIANT: case TOK_RAWVARIANT: case TOK_USERINVISIBLE: case TOK_USERBANNED: case TOK_USERLOCKED: case TOK_USERINCOMPLETE: case TOK_USERDISQUALIFIED: case TOK_LATEST: case TOK_LATESTMARKED: case TOK_AFTEROK: case TOK_EXAMINABLE: case TOK_CYPHER: case TOK_MISSINGSOURCE: case TOK_JUDGE_ID: case TOK_PASSED_MODE: case TOK_EOLN_TYPE: case TOK_STORE_FLAGS: case TOK_TOKEN_FLAGS: case TOK_TOKEN_COUNT: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i; if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE; if (r1.v.i < 0) return -FILTER_ERR_RANGE; switch (t->kind) { case TOK_TIME: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rentries[r1.v.i].time; break; case TOK_DUR: res->kind = TOK_DUR_L; res->type = FILTER_TYPE_DUR; res->v.u = env->rentries[r1.v.i].time - env->rhead.start_time; break; case TOK_SIZE: res->kind = TOK_SIZE_L; res->type = FILTER_TYPE_SIZE; res->v.z = env->rentries[r1.v.i].size; break; case TOK_HASH: res->kind = TOK_HASH_L; res->type = FILTER_TYPE_HASH; memcpy(res->v.h, env->rentries[r1.v.i].sha1, sizeof(env->cur->sha1)); break; case TOK_UUID: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; res->v.s = envdup(env, ej_uuid_unparse(&env->rentries[r1.v.i].run_uuid, "")); break; case TOK_IP: res->kind = TOK_IP_L; res->type = FILTER_TYPE_IP; run_entry_to_ipv6(&env->rentries[r1.v.i], &res->v.p); break; case TOK_PROB: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; prob_id = env->rentries[r1.v.i].prob_id; if (prob_id <= 0 || prob_id > env->maxprob || !env->probs[prob_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->probs[prob_id]->short_name); } break; case TOK_UID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].user_id; break; case TOK_LOGIN: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, user_id)); } break; case TOK_NAME: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, user_id)); } break; case TOK_GROUP: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; if (user_id > 0 && (u = teamdb_get_userlist(env->teamdb_state, user_id)) && u->cnts0 && (m = userlist_members_get_first(u->cnts0->members))) { res->v.s = envdup(env, m->group); } else { res->v.s = envdup(env, ""); } break; case TOK_LANG: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; lang_id = env->rentries[r1.v.i].lang_id; if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[lang_id]->short_name); } break; case TOK_ARCH: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; lang_id = env->rentries[r1.v.i].lang_id; if (lang_id <= 0 || lang_id > env->maxlang || !env->langs[lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[lang_id]->arch); } break; case TOK_RESULT: res->kind = TOK_RESULT_L; res->type = FILTER_TYPE_RESULT; res->v.r = env->rentries[r1.v.i].status; break; case TOK_SCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].score; break; case TOK_TEST: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].test; break; case TOK_IMPORTED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_imported; break; case TOK_HIDDEN: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_hidden; break; case TOK_READONLY: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_readonly; break; case TOK_MARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_marked; break; case TOK_SAVED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->rentries[r1.v.i].is_saved; break; case TOK_VARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->rentries[r1.v.i].variant; if (!c) { c = find_variant(env->serve_state, env->rentries[r1.v.i].user_id, env->rentries[r1.v.i].prob_id, 0); } res->v.i = c; break; case TOK_RAWVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->rentries[r1.v.i].variant; res->v.i = c; break; case TOK_USERINVISIBLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INVISIBLE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERBANNED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_BANNED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERLOCKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_LOCKED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERINCOMPLETE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INCOMPLETE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_USERDISQUALIFIED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->rentries[r1.v.i].user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_DISQUALIFIED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_LATEST: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latest(env, r1.v.i); break; case TOK_LATESTMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latestmarked(env, r1.v.i); break; case TOK_AFTEROK: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_afterok(env, r1.v.i); break; case TOK_EXAMINABLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; //res->v.b = env->rentries[r1.v.i].is_examinable; res->v.b = 0; break; case TOK_CYPHER: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->rentries[r1.v.i].user_id; u = 0; s = 0; if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id); if (u && u->cnts0) s = u->cnts0->exam_cypher; res->v.s = envdup(env, s); break; case TOK_MISSINGSOURCE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_missing_source(env, &env->rentries[r1.v.i]); break; case TOK_JUDGE_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rentries[r1.v.i].judge_id; break; case TOK_PASSED_MODE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.i = !!env->rentries[r1.v.i].passed_mode; break; case TOK_EOLN_TYPE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].eoln_type; break; case TOK_STORE_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].store_flags; break; case TOK_TOKEN_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].token_flags; break; case TOK_TOKEN_COUNT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = !!env->rentries[r1.v.i].token_count; break; default: abort(); } break; case TOK_INT: case TOK_STRING: case TOK_BOOL: case TOK_TIME_T: case TOK_DUR_T: case TOK_SIZE_T: case TOK_RESULT_T: case TOK_HASH_T: case TOK_IP_T: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; return filter_tree_eval_node(env->mem, t->kind, res, &r1, 0); /* variables */ case TOK_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rid; break; case TOK_CURTIME: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->cur->time; break; case TOK_CURDUR: res->kind = TOK_DUR_L; res->type = FILTER_TYPE_DUR; res->v.u = env->cur->time - env->rhead.start_time; break; case TOK_CURSIZE: res->kind = TOK_SIZE_L; res->type = FILTER_TYPE_SIZE; res->v.z = env->cur->size; break; case TOK_CURHASH: res->kind = TOK_HASH_L; res->type = FILTER_TYPE_HASH; memcpy(res->v.h, env->cur->sha1, sizeof(env->cur->sha1)); break; case TOK_CURUUID: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; res->v.s = envdup(env, ej_uuid_unparse(&env->cur->run_uuid, "")); break; case TOK_CURIP: res->kind = TOK_IP_L; res->type = FILTER_TYPE_IP; run_entry_to_ipv6(env->cur, &res->v.p); break; case TOK_CURPROB: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->prob_id <= 0 || env->cur->prob_id > env->maxprob || !env->probs[env->cur->prob_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->probs[env->cur->prob_id]->short_name); } break; case TOK_CURUID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->user_id; break; case TOK_CURLOGIN: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (!env->cur->user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_login(env->teamdb_state, env->cur->user_id)); } break; case TOK_CURNAME: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (!env->cur->user_id) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, teamdb_get_name(env->teamdb_state, env->cur->user_id)); } break; case TOK_CURGROUP: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->cur->user_id; if (user_id > 0 && (u = teamdb_get_userlist(env->teamdb_state, user_id)) && u->cnts0 && (m = userlist_members_get_first(u->cnts0->members))) { res->v.s = envdup(env, m->group); } else { res->v.s = envdup(env, ""); } break; case TOK_CURLANG: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[env->cur->lang_id]->short_name); } break; case TOK_CURARCH: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; if (env->cur->lang_id <= 0 || env->cur->lang_id > env->maxlang || !env->langs[env->cur->lang_id]) { res->v.s = envdup(env, ""); } else { res->v.s = envdup(env, env->langs[env->cur->lang_id]->arch); } break; case TOK_CURRESULT: res->kind = TOK_RESULT_L; res->type = FILTER_TYPE_RESULT; res->v.r = env->cur->status; break; case TOK_CURSCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->score; break; case TOK_CURTEST: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->test; break; case TOK_CURIMPORTED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_imported; break; case TOK_CURHIDDEN: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_hidden; break; case TOK_CURREADONLY: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_readonly; break; case TOK_CURMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_marked; break; case TOK_CURSAVED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = env->cur->is_saved; break; case TOK_CURVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->cur->variant; if (!c) c = find_variant(env->serve_state, env->cur->user_id, env->cur->prob_id, 0); res->v.i = c; break; case TOK_CURRAWVARIANT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; c = env->cur->variant; res->v.i = c; break; case TOK_CURUSERINVISIBLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INVISIBLE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERBANNED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_BANNED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERLOCKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_LOCKED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERINCOMPLETE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_INCOMPLETE)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURUSERDISQUALIFIED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; user_id = env->cur->user_id; if (!user_id) { res->v.b = 0; } else if ((flags = teamdb_get_flags(env->teamdb_state, user_id)) < 0) { res->v.b = 0; } else if ((flags & TEAM_DISQUALIFIED)) { res->v.b = 1; } else { res->v.b = 0; } break; case TOK_CURLATEST: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latest(env, env->cur->run_id); break; case TOK_CURLATESTMARKED: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_latestmarked(env, env->cur->run_id); break; case TOK_CURAFTEROK: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_afterok(env, env->cur->run_id); break; case TOK_CUREXAMINABLE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; //res->v.b = env->cur->is_examinable; res->v.b = 0; break; case TOK_CURCYPHER: res->kind = TOK_STRING_L; res->type = FILTER_TYPE_STRING; user_id = env->cur->user_id; u = 0; s = 0; if (user_id > 0) u = teamdb_get_userlist(env->teamdb_state, user_id); if (u && u->cnts0) s = u->cnts0->exam_cypher; res->v.s = envdup(env, s); break; case TOK_CURMISSINGSOURCE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = is_missing_source(env, env->cur); break; case TOK_CURJUDGE_ID: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->judge_id; break; case TOK_CURPASSED_MODE: res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.i = !!env->cur->passed_mode; break; case TOK_CUREOLN_TYPE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->eoln_type; break; case TOK_CURSTORE_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->store_flags; break; case TOK_CURTOKEN_FLAGS: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->token_flags; break; case TOK_CURTOKEN_COUNT: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->cur->token_count; break; case TOK_CURTOTAL_SCORE: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = serve_get_user_result_score(env->serve_state,env->cur->user_id); break; case TOK_NOW: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->cur_time; break; case TOK_START: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rhead.start_time; break; case TOK_FINISH: res->kind = TOK_TIME_L; res->type = FILTER_TYPE_TIME; res->v.a = env->rhead.stop_time; break; case TOK_TOTAL: res->kind = TOK_INT_L; res->type = FILTER_TYPE_INT; res->v.i = env->rtotal; break; case TOK_INT_L: case TOK_STRING_L: case TOK_BOOL_L: case TOK_TIME_L: case TOK_DUR_L: case TOK_SIZE_L: case TOK_RESULT_L: case TOK_HASH_L: case TOK_IP_L: *res = *t; return 0; case TOK_EXAMINATOR: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); if (r1.v.i < 0) r1.v.i = env->rtotal + r1.v.i; if (r1.v.i >= env->rtotal) return -FILTER_ERR_RANGE; if (r1.v.i < 0) return -FILTER_ERR_RANGE; if ((c = do_eval(env, t->v.t[1], &r2)) < 0) return c; ASSERT(r2.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = 0; /* for (c = 0; c < 3; c++) { if (env->rentries[r1.v.i].examiners[c] == r2.v.i) { res->v.b = 1; break; } } */ break; case TOK_CUREXAMINATOR: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = 0; /* for (c = 0; c < 3; c++) { if (env->cur->examiners[c] == r1.v.i) { res->v.b = 1; break; } } */ break; case TOK_INUSERGROUP: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_STRING_L); if ((c = find_user_group(env, r1.v.s)) < 0) return c; t->kind = TOK_INUSERGROUPINT; t->v.t[0] = filter_tree_new_int(env->mem, c); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = check_user_group(env, env->cur->user_id, c); break; case TOK_INUSERGROUPINT: if ((c = do_eval(env, t->v.t[0], &r1)) < 0) return c; ASSERT(r1.kind == TOK_INT_L); res->kind = TOK_BOOL_L; res->type = FILTER_TYPE_BOOL; res->v.b = check_user_group(env, env->cur->user_id, r1.v.i); break; default: SWERR(("unhandled kind: %d", t->kind)); } return 0; }
int check_conf(char** kasp) { int status = 0; int i = 0; int j = 0; int temp_status = 0; xmlDocPtr doc; xmlXPathContextPtr xpath_ctx; xmlXPathObjectPtr xpath_obj; xmlNode *curNode; xmlChar *xexpr; char* temp_char = NULL; KC_REPO* repo = NULL; int* repo_mods = NULL; /* To see if we have looked at this module before */ const char* rngfilename = OPENDNSSEC_SCHEMA_DIR "/conf.rng"; const char* zonerngfilename = OPENDNSSEC_SCHEMA_DIR "/zonelist.rng"; /* Check that the file is well-formed */ status = check_rng(config, rngfilename); if (status == 0) { dual_log("INFO: The XML in %s is valid\n", config); } else { return status; /* Don't try to read the file if it is invalid */ } /* Load XML document */ doc = xmlParseFile(config); if (doc == NULL) { return 1; } /* Create xpath evaluation context */ xpath_ctx = xmlXPathNewContext(doc); if(xpath_ctx == NULL) { xmlFreeDoc(doc); return 1; } /* REPOSITORY section */ xexpr = (xmlChar *)"//Configuration/RepositoryList/Repository"; xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx); if(xpath_obj == NULL) { xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(doc); return 1; } if (xpath_obj->nodesetval) { repo_count = xpath_obj->nodesetval->nodeNr; repo = (KC_REPO*)malloc(sizeof(KC_REPO) * repo_count); repo_mods = (int*)malloc(sizeof(int) * repo_count); repo_list = (char**)malloc(sizeof(char*) * repo_count); if (repo == NULL || repo_mods == NULL || repo_list == NULL) { dual_log("ERROR: malloc for repo information failed\n"); exit(1); } for (i = 0; i < repo_count; i++) { repo_mods[i] = 0; curNode = xpath_obj->nodesetval->nodeTab[i]->xmlChildrenNode; /* Default for capacity */ repo[i].name = (char *) xmlGetProp(xpath_obj->nodesetval->nodeTab[i], (const xmlChar *)"name"); repo_list[i] = StrStrdup(repo[i].name); while (curNode) { if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel")) repo[i].TokenLabel = (char *) xmlNodeGetContent(curNode); if (xmlStrEqual(curNode->name, (const xmlChar *)"Module")) repo[i].module = (char *) xmlNodeGetContent(curNode); curNode = curNode->next; } } } xmlXPathFreeObject(xpath_obj); /* Now we have all the information we need do the checks */ for (i = 0; i < repo_count; i++) { if (repo_mods[i] == 0) { /* 1) Check that the module exists */ status += check_file(repo[i].module, "Module"); repo_mods[i] = 1; /* Done this module */ /* 2) Check repos on the same modules have different TokenLabels */ for (j = i+1; j < repo_count; j++) { if ( repo_mods[j] == 0 && (strcmp(repo[i].module, repo[j].module) == 0) ) { repo_mods[j] = 1; /* done */ if (strcmp(repo[i].TokenLabel, repo[j].TokenLabel) == 0) { dual_log("ERROR: Multiple Repositories (%s and %s) in %s have the same Module (%s) and TokenLabel (%s)\n", repo[i].name, repo[j].name, config, repo[i].module, repo[i].TokenLabel); status += 1; } } } } /* 3) Check that the name is unique */ for (j = i+1; j < repo_count; j++) { if (strcmp(repo[i].name, repo[j].name) == 0) { dual_log("ERROR: Two repositories exist with the same name (%s)\n", repo[i].name); status += 1; } } } /* COMMON section */ /* PolicyFile (aka KASP); we will validate it later */ if (*kasp == NULL) { xexpr = (xmlChar *)"//Configuration/Common/PolicyFile"; xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx); if(xpath_obj == NULL) { xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(doc); for (i = 0; i < repo_count; i++) { free(repo[i].name); free(repo[i].module); free(repo[i].TokenLabel); } free(repo); free(repo_mods); return -1; } temp_char = (char*) xmlXPathCastToString(xpath_obj); StrAppend(kasp, temp_char); StrFree(temp_char); xmlXPathFreeObject(xpath_obj); } /* Check that the Zonelist file is well-formed */ xexpr = (xmlChar *)"//Configuration/Common/ZoneListFile"; xpath_obj = xmlXPathEvalExpression(xexpr, xpath_ctx); if(xpath_obj == NULL) { xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(doc); for (i = 0; i < repo_count; i++) { free(repo[i].name); free(repo[i].module); free(repo[i].TokenLabel); } free(repo); free(repo_mods); return -1; } temp_char = (char*) xmlXPathCastToString(xpath_obj); if (check_rng(temp_char, zonerngfilename) == 0) { dual_log("INFO: The XML in %s is valid\n", temp_char); } else { status += 1; } xmlXPathFreeObject(xpath_obj); StrFree(temp_char); /* ENFORCER section */ /* Check defined user/group */ status += check_user_group(xpath_ctx, (xmlChar *)"//Configuration/Enforcer/Privileges/User", (xmlChar *)"//Configuration/Enforcer/Privileges/Group"); /* Check datastore exists (if sqlite) */ /* TODO check datastore matches libksm without building against libksm */ temp_status = check_file_from_xpath(xpath_ctx, "SQLite datastore", (xmlChar *)"//Configuration/Enforcer/Datastore/SQLite"); if (temp_status == -1) { /* Configured for Mysql DB */ /*if (DbFlavour() != MYSQL_DB) { dual_log("ERROR: libksm compiled for sqlite3 but conf.xml configured for MySQL\n"); }*/ } else { status += temp_status; /* Configured for sqlite DB */ /*if (DbFlavour() != SQLITE_DB) { dual_log("ERROR: libksm compiled for MySQL but conf.xml configured for sqlite3\n"); }*/ } /* Warn if Interval is M or Y */ status += check_time_def_from_xpath(xpath_ctx, (xmlChar *)"//Configuration/Enforcer/Interval", "Configuration", "Enforcer/Interval", config); /* Warn if RolloverNotification is M or Y */ status += check_time_def_from_xpath(xpath_ctx, (xmlChar *)"//Configuration/Enforcer/RolloverNotification", "Configuration", "Enforcer/RolloverNotification", config); /* Check DelegationSignerSubmitCommand exists (if set) */ temp_status = check_file_from_xpath(xpath_ctx, "DelegationSignerSubmitCommand", (xmlChar *)"//Configuration/Enforcer/DelegationSignerSubmitCommand"); if (temp_status > 0) { status += temp_status; } /* SIGNER section */ /* Check defined user/group */ status += check_user_group(xpath_ctx, (xmlChar *)"//Configuration/Signer/Privileges/User", (xmlChar *)"//Configuration/Signer/Privileges/Group"); /* Check WorkingDirectory exists (or default) */ temp_status = check_path_from_xpath(xpath_ctx, "WorkingDirectory", (xmlChar *)"//Configuration/Signer/WorkingDirectory"); if (temp_status == -1) { /* Check the default location */ check_path(OPENDNSSEC_STATE_DIR "/tmp", "default WorkingDirectory"); } else { status += temp_status; } xmlXPathFreeContext(xpath_ctx); xmlFreeDoc(doc); for (i = 0; i < repo_count; i++) { free(repo[i].name); free(repo[i].module); free(repo[i].TokenLabel); } free(repo); free(repo_mods); return status; }