cache_entry register_new_mp_cache_entry(struct query_state *qstate, const char *dec_cache_entry_name) { cache_entry c_entry; char *en_bkp; TRACE_IN(register_new_mp_cache_entry); c_entry = INVALID_CACHE_ENTRY; configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); configuration_lock_wrlock(s_configuration); en_bkp = qstate->config_entry->mp_cache_params.cep.entry_name; qstate->config_entry->mp_cache_params.cep.entry_name = (char *)dec_cache_entry_name; register_cache_entry(s_cache, (struct cache_entry_params *) &qstate->config_entry->mp_cache_params); qstate->config_entry->mp_cache_params.cep.entry_name = en_bkp; configuration_unlock(s_configuration); configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, dec_cache_entry_name); configuration_unlock(s_configuration); configuration_entry_add_mp_cache_entry(qstate->config_entry, c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); TRACE_OUT(register_new_mp_cache_entry); return (c_entry); }
void t_auth::remove_from_cache(const string &realm) { if (realm.empty()) { cache.clear(); } else { list<t_cr_cache_entry>::iterator i = find_cache_entry(t_url(), realm); if (i != cache.end()) { cache.erase(i); } } }
void t_auth::update_cache(const t_url &to, const t_credentials &cr, const string &passwd, bool proxy) { list<t_cr_cache_entry>::iterator i, j; i = find_cache_entry(to, cr.digest_response.realm, proxy); if (i == cache.end()) { if (cache.size() > AUTH_CACHE_SIZE) { cache.erase(cache.begin()); } cache.push_back(t_cr_cache_entry(to, cr, passwd, proxy)); } else { i->credentials = cr; i->passwd = passwd; // Move cache entry to end of the cache. // TODO: this can be more efficient by checking if the // entry is already at the end. t_cr_cache_entry e = *i; cache.erase(i); cache.push_back(e); } }
static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, struct name_entry *names, struct traverse_info *info) { struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, }; struct unpack_trees_options *o = info->data; const struct name_entry *p = names; /* Find first entry with a real name (we could use "mask" too) */ while (!p->mode) p++; if (o->debug_unpack) debug_unpack_callback(n, mask, dirmask, names, info); /* Are we supposed to look at the index too? */ if (o->merge) { while (1) { int cmp; struct cache_entry *ce; if (o->diff_index_cached) ce = next_cache_entry(o); else ce = find_cache_entry(info, p); if (!ce) break; cmp = compare_entry(ce, info, p); if (cmp < 0) { if (unpack_index_entry(ce, o) < 0) return unpack_failed(o, NULL); continue; } if (!cmp) { if (ce_stage(ce)) { /* * If we skip unmerged index * entries, we'll skip this * entry *and* the tree * entries associated with it! */ if (o->skip_unmerged) { add_same_unmerged(ce, o); return mask; } } src[0] = ce; } break; } } if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0) return -1; if (o->merge && src[0]) { if (ce_stage(src[0])) mark_ce_used_same_name(src[0], o); else mark_ce_used(src[0], o); } /* Now handle any directories.. */ if (dirmask) { /* special case: "diff-index --cached" looking at a tree */ if (o->diff_index_cached && n == 1 && dirmask == 1 && S_ISDIR(names->mode)) { int matches; matches = cache_tree_matches_traversal(o->src_index->cache_tree, names, info); /* * Everything under the name matches; skip the * entire hierarchy. diff_index_cached codepath * special cases D/F conflicts in such a way that * it does not do any look-ahead, so this is safe. */ if (matches) { o->cache_bottom += matches; return mask; } } if (traverse_trees_recursive(n, dirmask, mask & ~dirmask, names, info) < 0) return -1; return mask; } return mask; }
static int on_read_request_process(struct query_state *qstate) { struct cache_read_request *read_request; struct cache_read_response *read_response; cache_entry c_entry, neg_c_entry; struct agent *lookup_agent; struct common_agent *c_agent; int res; TRACE_IN(on_read_request_process); init_comm_element(&qstate->response, CET_READ_RESPONSE); read_response = get_cache_read_response(&qstate->response); read_request = get_cache_read_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, read_request->entry); if (qstate->config_entry == NULL) { read_response->error_code = ENOENT; LOG_ERR_2("read_request", "can't find configuration " "entry '%s'. aborting request", read_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { read_response->error_code = EACCES; LOG_ERR_2("read_request", "configuration entry '%s' is disabled", read_request->entry); goto fin; } /* * if we perform lookups by ourselves, then we don't need to separate * cache entries by euid and egid */ if (qstate->config_entry->perform_actual_lookups != 0) memset(read_request->cache_key, 0, qstate->eid_str_length); else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { /* if the lookup is not self-performing, we check for clients euid/egid */ read_response->error_code = EPERM; goto fin; } #endif } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, qstate->config_entry->positive_cache_params.entry_name); neg_c_entry = find_cache_entry(s_cache, qstate->config_entry->negative_cache_params.entry_name); configuration_unlock(s_configuration); if ((c_entry != NULL) && (neg_c_entry != NULL)) { configuration_lock_entry(qstate->config_entry, CELT_POSITIVE); qstate->config_entry->positive_cache_entry = c_entry; read_response->error_code = cache_read(c_entry, read_request->cache_key, read_request->cache_key_size, NULL, &read_response->data_size); if (read_response->error_code == -2) { read_response->data = (char *)malloc( read_response->data_size); assert(read_response != NULL); read_response->error_code = cache_read(c_entry, read_request->cache_key, read_request->cache_key_size, read_response->data, &read_response->data_size); } configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE); configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); qstate->config_entry->negative_cache_entry = neg_c_entry; if (read_response->error_code == -1) { read_response->error_code = cache_read(neg_c_entry, read_request->cache_key, read_request->cache_key_size, NULL, &read_response->data_size); if (read_response->error_code == -2) { read_response->error_code = 0; read_response->data = NULL; read_response->data_size = 0; } } configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); if ((read_response->error_code == -1) && (qstate->config_entry->perform_actual_lookups != 0)) { free(read_response->data); read_response->data = NULL; read_response->data_size = 0; lookup_agent = find_agent(s_agent_table, read_request->entry, COMMON_AGENT); if ((lookup_agent != NULL) && (lookup_agent->type == COMMON_AGENT)) { c_agent = (struct common_agent *)lookup_agent; res = c_agent->lookup_func( read_request->cache_key + qstate->eid_str_length, read_request->cache_key_size - qstate->eid_str_length, &read_response->data, &read_response->data_size); if (res == NS_SUCCESS) { read_response->error_code = 0; configuration_lock_entry( qstate->config_entry, CELT_POSITIVE); cache_write(c_entry, read_request->cache_key, read_request->cache_key_size, read_response->data, read_response->data_size); configuration_unlock_entry( qstate->config_entry, CELT_POSITIVE); } else if ((res == NS_NOTFOUND) || (res == NS_RETURN)) { configuration_lock_entry( qstate->config_entry, CELT_NEGATIVE); cache_write(neg_c_entry, read_request->cache_key, read_request->cache_key_size, negative_data, sizeof(negative_data)); configuration_unlock_entry( qstate->config_entry, CELT_NEGATIVE); read_response->error_code = 0; read_response->data = NULL; read_response->data_size = 0; } } } if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || (qstate->config_entry->common_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->common_query_timeout, sizeof(struct timeval)); } else read_response->error_code = -1; fin: qstate->kevent_filter = EVFILT_WRITE; if (read_response->error_code == 0) qstate->kevent_watermark = sizeof(int) + sizeof(size_t); else qstate->kevent_watermark = sizeof(int); qstate->process_func = on_read_response_write1; TRACE_OUT(on_read_request_process); return (0); }
static int on_negative_write_request_process(struct query_state *qstate) { struct cache_write_request *write_request; struct cache_write_response *write_response; cache_entry c_entry; TRACE_IN(on_negative_write_request_process); init_comm_element(&qstate->response, CET_WRITE_RESPONSE); write_response = get_cache_write_response(&qstate->response); write_request = get_cache_write_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, write_request->entry); if (qstate->config_entry == NULL) { write_response->error_code = ENOENT; LOG_ERR_2("negative_write_request", "can't find configuration" " entry '%s'. aborting request", write_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { write_response->error_code = EACCES; LOG_ERR_2("negative_write_request", "configuration entry '%s' is disabled", write_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { write_response->error_code = EOPNOTSUPP; LOG_ERR_2("negative_write_request", "entry '%s' performs lookups by itself: " "can't write to it", write_request->entry); goto fin; } else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { write_response->error_code = EPERM; goto fin; } #endif } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, qstate->config_entry->negative_cache_params.entry_name); configuration_unlock(s_configuration); if (c_entry != NULL) { configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); qstate->config_entry->negative_cache_entry = c_entry; write_response->error_code = cache_write(c_entry, write_request->cache_key, write_request->cache_key_size, negative_data, sizeof(negative_data)); configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || (qstate->config_entry->common_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->common_query_timeout, sizeof(struct timeval)); } else write_response->error_code = -1; fin: qstate->kevent_filter = EVFILT_WRITE; qstate->kevent_watermark = sizeof(int); qstate->process_func = on_write_response_write1; TRACE_OUT(on_negative_write_request_process); return (0); }
static int on_mp_write_session_request_process(struct query_state *qstate) { struct cache_mp_write_session_request *c_mp_ws_request; struct cache_mp_write_session_response *c_mp_ws_response; cache_mp_write_session ws; cache_entry c_entry; char *dec_cache_entry_name; TRACE_IN(on_mp_write_session_request_process); init_comm_element(&qstate->response, CET_MP_WRITE_SESSION_RESPONSE); c_mp_ws_response = get_cache_mp_write_session_response( &qstate->response); c_mp_ws_request = get_cache_mp_write_session_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, c_mp_ws_request->entry); if (qstate->config_entry == NULL) { c_mp_ws_response->error_code = ENOENT; LOG_ERR_2("write_session_request", "can't find configuration entry '%s'. " "aborting request", c_mp_ws_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { c_mp_ws_response->error_code = EACCES; LOG_ERR_2("write_session_request", "configuration entry '%s' is disabled", c_mp_ws_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { c_mp_ws_response->error_code = EOPNOTSUPP; LOG_ERR_2("write_session_request", "entry '%s' performs lookups by itself: " "can't write to it", c_mp_ws_request->entry); goto fin; } else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { c_mp_ws_response->error_code = EPERM; goto fin; } #endif } /* * All multipart entries are separated by their name decorations. * For one configuration entry there will be a lot of multipart * cache entries - each with its own decorated name. */ asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->mp_cache_params.cep.entry_name); assert(dec_cache_entry_name != NULL); configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, dec_cache_entry_name); configuration_unlock(s_configuration); if (c_entry == INVALID_CACHE_ENTRY) c_entry = register_new_mp_cache_entry(qstate, dec_cache_entry_name); free(dec_cache_entry_name); assert(c_entry != NULL); configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); ws = open_cache_mp_write_session(c_entry); if (ws == INVALID_CACHE_MP_WRITE_SESSION) c_mp_ws_response->error_code = -1; else { qstate->mdata = ws; qstate->destroy_func = on_mp_write_session_destroy; if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) || (qstate->config_entry->mp_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->mp_query_timeout, sizeof(struct timeval)); } configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); fin: qstate->process_func = on_mp_write_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; TRACE_OUT(on_mp_write_session_request_process); return (0); }
static int on_mp_read_session_request_process(struct query_state *qstate) { struct cache_mp_read_session_request *c_mp_rs_request; struct cache_mp_read_session_response *c_mp_rs_response; cache_mp_read_session rs; cache_entry c_entry; char *dec_cache_entry_name; char *buffer; size_t buffer_size; cache_mp_write_session ws; struct agent *lookup_agent; struct multipart_agent *mp_agent; void *mdata; int res; TRACE_IN(on_mp_read_session_request_process); init_comm_element(&qstate->response, CET_MP_READ_SESSION_RESPONSE); c_mp_rs_response = get_cache_mp_read_session_response( &qstate->response); c_mp_rs_request = get_cache_mp_read_session_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, c_mp_rs_request->entry); if (qstate->config_entry == NULL) { c_mp_rs_response->error_code = ENOENT; LOG_ERR_2("read_session_request", "can't find configuration entry '%s'." " aborting request", c_mp_rs_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { c_mp_rs_response->error_code = EACCES; LOG_ERR_2("read_session_request", "configuration entry '%s' is disabled", c_mp_rs_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) dec_cache_entry_name = strdup( qstate->config_entry->mp_cache_params.cep.entry_name); else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { c_mp_rs_response->error_code = EPERM; goto fin; } #endif asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->mp_cache_params.cep.entry_name); } assert(dec_cache_entry_name != NULL); configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, dec_cache_entry_name); configuration_unlock(s_configuration); if ((c_entry == INVALID_CACHE) && (qstate->config_entry->perform_actual_lookups != 0)) c_entry = register_new_mp_cache_entry(qstate, dec_cache_entry_name); free(dec_cache_entry_name); if (c_entry != INVALID_CACHE_ENTRY) { configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); rs = open_cache_mp_read_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); if ((rs == INVALID_CACHE_MP_READ_SESSION) && (qstate->config_entry->perform_actual_lookups != 0)) { lookup_agent = find_agent(s_agent_table, c_mp_rs_request->entry, MULTIPART_AGENT); if ((lookup_agent != NULL) && (lookup_agent->type == MULTIPART_AGENT)) { mp_agent = (struct multipart_agent *) lookup_agent; mdata = mp_agent->mp_init_func(); /* * Multipart agents read the whole snapshot * of the data at one time. */ configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); ws = open_cache_mp_write_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); if (ws != NULL) { do { buffer = NULL; res = mp_agent->mp_lookup_func(&buffer, &buffer_size, mdata); if ((res & NS_TERMINATE) && (buffer != NULL)) { configuration_lock_entry( qstate->config_entry, CELT_MULTIPART); if (cache_mp_write(ws, buffer, buffer_size) != 0) { abandon_cache_mp_write_session(ws); ws = NULL; } configuration_unlock_entry( qstate->config_entry, CELT_MULTIPART); free(buffer); buffer = NULL; } else { configuration_lock_entry( qstate->config_entry, CELT_MULTIPART); close_cache_mp_write_session(ws); configuration_unlock_entry( qstate->config_entry, CELT_MULTIPART); free(buffer); buffer = NULL; } } while ((res & NS_TERMINATE) && (ws != NULL)); } configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); rs = open_cache_mp_read_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); } } if (rs == INVALID_CACHE_MP_READ_SESSION) c_mp_rs_response->error_code = -1; else { qstate->mdata = rs; qstate->destroy_func = on_mp_read_session_destroy; configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) || (qstate->config_entry->mp_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->mp_query_timeout, sizeof(struct timeval)); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); } } else c_mp_rs_response->error_code = -1; fin: qstate->process_func = on_mp_read_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; TRACE_OUT(on_mp_read_session_request_process); return (0); }
bool t_auth::authorize(t_user *user_config, t_request *r, t_response *resp) { string username; string passwd; list<t_cr_cache_entry>::iterator i; t_challenge c; bool proxy; assert(resp->must_authenticate()); if (resp->code == R_401_UNAUTHORIZED) { c = resp->hdr_www_authenticate.challenge; proxy = false; } else { c = resp->hdr_proxy_authenticate.challenge; proxy = true; } // Only DIGEST is supported if (c.auth_scheme != AUTH_DIGEST) { log_file->write_header("t_auth::authorize"); log_file->write_raw("Unsupported authentication scheme: "); log_file->write_raw(c.auth_scheme); log_file->write_endl(); log_file->write_footer(); return false; } const t_digest_challenge &dc = c.digest_challenge; i = find_cache_entry(r->uri, dc.realm, proxy); if (auth_failed(r, c, proxy)) { // The current credentials are wrong. Remove them and // ask the user for a username and password. remove_credentials(r, c, proxy); } else { // Determine user name and password if (i != cache.end()) { username = i->credentials.digest_response.username; passwd = i->passwd; } else if (dc.realm == user_config->get_auth_realm() || user_config->get_auth_realm() == "") { username = user_config->get_auth_name(); passwd = user_config->get_auth_pass(); } if (dc.stale) { // The current credentials are stale. Remove them. remove_credentials(r, c, proxy); } } // Ask user for username/password if ((username == "" || passwd == "") && !re_register) { if (!ui->cb_ask_credentials(user_config, dc.realm, username, passwd)) { log_file->write_report("Asking user name and password failed.", "t_auth::authorize"); return false; } } // No valid username/passwd if (username == "" && passwd == "") { log_file->write_report("Incorrect user name and/or password.", "t_auth::authorize"); return false; } bool auth_success; string fail_reason; if (!proxy) { t_credentials cr; auth_success = r->www_authorize(c, user_config, username, passwd, 1, NEW_CNONCE, cr, fail_reason); if (auth_success) { update_cache(r->uri, cr, passwd, proxy); } } else { t_credentials cr; auth_success = r->proxy_authorize(c, user_config, username, passwd, 1, NEW_CNONCE, cr, fail_reason); if (auth_success) { update_cache(r->uri, cr, passwd, proxy); } } if (!auth_success) { log_file->write_report(fail_reason, "t_auth::authorize"); return false; } return true; }