int os_object_get(os_t os, os_object_t o, const char *key, void **val, os_type_t type, os_type_t *ot) { os_field_t osf; nad_t nad; /* Type complexity is to deal with string/NADs. If an object contains xml, it will only be parsed and returned as a NAD if type == os_type_NAD, otherwise if type == os_type_UNKNOWN it will be returned as string, unless it's already been converted to a NAD */ osf = (os_field_t) xhash_get(o->hash, key); if(osf == NULL) { *val = NULL; return 0; } if (ot != NULL) *ot = osf->type; if (type == os_type_UNKNOWN) type = osf->type; if (type == os_type_UNKNOWN) type = osf->type; switch(type) { case os_type_BOOLEAN: case os_type_INTEGER: * (int *) val = (int) (intptr_t) osf->val; break; case os_type_STRING: *val = osf->val; break; case os_type_NAD: /* check to see whether it's already a NAD */ if (osf->type == os_type_NAD) { *val = osf->val; } else { /* parse the string into a NAD */ nad = nad_parse(((char *) osf->val) + 3, strlen(osf->val) - 3); if(nad == NULL) { /* unparseable NAD */ log_debug(ZONE, "cell returned from storage for key %s has unparseable XML content (%lu bytes)", key, strlen(osf->val)-3); *val = NULL; return 0; } /* replace the string with a NAD */ osf->val = (void *) nad; pool_cleanup(os->p, (pool_cleanup_t) nad_free, (void *) nad); *val = osf->val; osf->type = os_type_NAD; } break; default: *val = NULL; } log_debug(ZONE, "got field %s (val %x type %d) to object", key, *val, type); return 1; }
int filter_load(router_t r) { char *filterfile; FILE *f; long size; char *buf; nad_t nad; int i, nfilters, filter, from, to, what, redirect, error, log; acl_t list_tail, acl; log_debug(ZONE, "loading filter"); if(r->filter != NULL) filter_unload(r); filterfile = config_get_one(r->config, "aci.filter", 0); if(filterfile == NULL) filterfile = CONFIG_DIR "/router-filter.xml"; f = fopen(filterfile, "rb"); if(f == NULL) { log_write(r->log, LOG_NOTICE, "couldn't open filter file %s: %s", filterfile, strerror(errno)); r->filter_load = time(NULL); return 0; } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); buf = (char *) malloc(sizeof(char) * size); if (fread(buf, 1, size, f) != size || ferror(f)) { log_write(r->log, LOG_ERR, "couldn't read from filter file: %s", strerror(errno)); free(buf); fclose(f); return 1; } fclose(f); nad = nad_parse(buf, size); if(nad == NULL) { log_write(r->log, LOG_ERR, "couldn't parse filter file"); free(buf); return 1; } free(buf); list_tail = NULL; log_debug(ZONE, "building filter list"); nfilters = 0; filter = nad_find_elem(nad, 0, -1, "rule", 1); while(filter >= 0) { from = nad_find_attr(nad, filter, -1, "from", NULL); to = nad_find_attr(nad, filter, -1, "to", NULL); what = nad_find_attr(nad, filter, -1, "what", NULL); redirect = nad_find_attr(nad, filter, -1, "redirect", NULL); error = nad_find_attr(nad, filter, -1, "error", NULL); log = nad_find_attr(nad, filter, -1, "log", NULL); acl = (acl_t) calloc(1, sizeof(struct acl_s)); if(from >= 0) { if (NAD_AVAL_L(nad, from) == 0 ) acl->from = NULL; else { acl->from = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, from) + 1)); sprintf(acl->from, "%.*s", NAD_AVAL_L(nad, from), NAD_AVAL(nad, from)); } } if(to >= 0) { if (NAD_AVAL_L(nad, to) == 0 ) acl->to = NULL; else { acl->to = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, to) + 1)); sprintf(acl->to, "%.*s", NAD_AVAL_L(nad, to), NAD_AVAL(nad, to)); } } if(what >= 0) { if (NAD_AVAL_L(nad, what) == 0 || strncmp(NAD_AVAL(nad, what), "*", NAD_AVAL_L(nad, what)) == 0) acl->what = NULL; else { acl->what = (char *) malloc(sizeof(char) * (NAD_AVAL_L(nad, what) + 1)); sprintf(acl->what, "%.*s", NAD_AVAL_L(nad, what), NAD_AVAL(nad, what)); } } if(redirect >= 0) { if (NAD_AVAL_L(nad, redirect) == 0) acl->redirect = NULL; else { acl->redirect_len = NAD_AVAL_L(nad, redirect); acl->redirect = (char *) malloc(sizeof(char) * (acl->redirect_len + 1)); sprintf(acl->redirect, "%.*s", acl->redirect_len, NAD_AVAL(nad, redirect)); acl->error = stanza_err_REDIRECT; } } if(error >= 0) { acl->error = stanza_err_NOT_ALLOWED; for(i=0; _stanza_errors[i].code != NULL; i++) { if(_stanza_errors[i].name != NULL && strncmp(_stanza_errors[i].name, NAD_AVAL(nad, error), NAD_AVAL_L(nad, error)) == 0) { acl->error = stanza_err_BAD_REQUEST + i; break; } } } if(log >= 0) { acl->log = ! strncasecmp(NAD_AVAL(nad, log), "YES", NAD_AVAL_L(nad, log)); acl->log |= ! strncasecmp(NAD_AVAL(nad, log), "ON", NAD_AVAL_L(nad, log)); } if(list_tail != NULL) { list_tail->next = acl; list_tail = acl; } /* record the head of the list */ if(r->filter == NULL) { r->filter = acl; list_tail = acl; } log_debug(ZONE, "added %s rule: from=%s, to=%s, what=%s, redirect=%s, error=%d, log=%s", (acl->error?"deny":"allow"), acl->from, acl->to, acl->what, acl->redirect, acl->error, (acl->log?"yes":"no")); nfilters++; filter = nad_find_elem(nad, filter, -1, "rule", 0); } nad_free(nad); log_write(r->log, LOG_NOTICE, "loaded filters (%d rules)", nfilters); r->filter_load = time(NULL); return 0; }
int user_table_load(router_t r) { const char *userfile; FILE *f; long size; char *buf; nad_t nad; int nusers, user, name, secret; log_debug(ZONE, "loading user table"); if(r->users != NULL) xhash_free(r->users); r->users = xhash_new(51); userfile = config_get_one(r->config, "local.users", 0); if(userfile == NULL) userfile = CONFIG_DIR "/router-users.xml"; f = fopen(userfile, "rb"); if(f == NULL) { log_write(r->log, LOG_ERR, "couldn't open user table file %s: %s", userfile, strerror(errno)); return 1; } fseek(f, 0, SEEK_END); size = ftell(f); if(size < 0) { log_write(r->log, LOG_ERR, "couldn't seek user table file %s: %s", userfile, strerror(errno)); fclose(f); return 1; } if(size == 0) { log_write(r->log, LOG_ERR, "empty user table file %s", userfile); fclose(f); return 1; } fseek(f, 0, SEEK_SET); buf = (char *) malloc(sizeof(char) * size); if (fread(buf, 1, size, f) != size || ferror(f)) { log_write(r->log, LOG_ERR, "couldn't read from user table file: %s", strerror(errno)); free(buf); fclose(f); return 1; } fclose(f); nad = nad_parse(buf, size); if(nad == NULL) { log_write(r->log, LOG_ERR, "couldn't parse user table"); free(buf); return 1; } free(buf); nusers = 0; user = nad_find_elem(nad, 0, -1, "user", 1); while(user >= 0) { name = nad_find_elem(nad, user, -1, "name", 1); secret = nad_find_elem(nad, user, -1, "secret", 1); if(name < 0 || secret < 0 || NAD_CDATA_L(nad, name) <= 0 || NAD_CDATA_L(nad, secret) <= 0) { log_write(r->log, LOG_ERR, "malformed user entry in user table file, skipping"); continue; } log_debug(ZONE, "remembering user '%.*s'", NAD_CDATA_L(nad, name), NAD_CDATA(nad, name)); xhash_put(r->users, pstrdupx(xhash_pool(r->users), NAD_CDATA(nad, name), NAD_CDATA_L(nad, name)), pstrdupx(xhash_pool(r->users), NAD_CDATA(nad, secret), NAD_CDATA_L(nad, secret))); nusers++; user = nad_find_elem(nad, user, -1, "user", 0); } nad_free(nad); log_write(r->log, LOG_NOTICE, "loaded user table (%d users)", nusers); r->users_load = time(NULL); return 0; }