/* Before sending the signal to the pid this function verifies that * the pid is a member of the current process group; either using * apr_proc_wait(), where waitpid() guarantees to fail for non-child * processes; or by using getpgid() directly, if available. */ AP_DECLARE(apr_status_t) ap_mpm_safe_kill(pid_t pid, int sig) { #ifndef HAVE_GETPGID apr_proc_t proc; apr_status_t rv; apr_exit_why_e why; int status; /* Ensure pid sanity */ if (pid < 1) { return APR_EINVAL; } proc.pid = pid; rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); if (rv == APR_CHILD_DONE) { /* The child already died - log the termination status if * necessary: */ ap_process_child_status(&proc, why, status); return APR_EINVAL; } else if (rv != APR_CHILD_NOTDONE) { /* The child is already dead and reaped, or was a bogus pid - * log this either way. */ ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00048) "cannot send signal %d to pid %ld (non-child or " "already dead)", sig, (long)pid); return APR_EINVAL; } #else pid_t pg; /* Ensure pid sanity. */ if (pid < 1) { return APR_EINVAL; } pg = getpgid(pid); if (pg == -1) { /* Process already dead... */ return errno; } if (pg != getpgrp()) { ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf, APLOGNO(00049) "refusing to send signal %d to pid %ld outside " "process group", sig, (long)pid); return APR_EINVAL; } #endif return kill(pid, sig) ? errno : APR_SUCCESS; }
static authn_status get_realm_hash(request_rec *r, const char *user, const char *realm, char **rethash) { authn_file_config_rec *conf = ap_get_module_config(r->per_dir_config, &authn_file_module); ap_configfile_t *f; char l[MAX_STRING_LEN]; apr_status_t status; char *file_hash = NULL; if (!conf->pwfile) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01621) "AuthUserFile not specified in the configuration"); return AUTH_GENERAL_ERROR; } status = ap_pcfg_openfile(&f, r->pool, conf->pwfile); if (status != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01622) "Could not open password file: %s", conf->pwfile); return AUTH_GENERAL_ERROR; } while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) { const char *rpw, *w, *x; /* Skip # or blank lines. */ if ((l[0] == '#') || (!l[0])) { continue; } rpw = l; w = ap_getword(r->pool, &rpw, ':'); x = ap_getword(r->pool, &rpw, ':'); if (x && w && !strcmp(user, w) && !strcmp(realm, x)) { /* Remember that this is a md5 hash of user:realm:password. */ file_hash = ap_getword(r->pool, &rpw, ':'); break; } } ap_cfg_closefile(f); if (!file_hash) { return AUTH_USER_NOT_FOUND; } *rethash = file_hash; AUTHN_CACHE_STORE(r, user, realm, file_hash); return AUTH_USER_FOUND; }
static apr_status_t restore_slotmem(void *ptr, const char *storename, apr_size_t size, apr_pool_t *pool) { apr_file_t *fp; apr_size_t nbytes = size; apr_status_t rv = APR_SUCCESS; unsigned char digest[APR_MD5_DIGESTSIZE]; unsigned char digest2[APR_MD5_DIGESTSIZE]; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335) "restoring %s", storename); if (storename) { rv = apr_file_open(&fp, storename, APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); if (rv == APR_SUCCESS) { rv = apr_file_read(fp, ptr, &nbytes); if ((rv == APR_SUCCESS || rv == APR_EOF) && nbytes == size) { rv = APR_SUCCESS; /* for successful return @ EOF */ /* * if at EOF, don't bother checking md5 * - backwards compatibility * */ if (apr_file_eof(fp) != APR_EOF) { apr_size_t ds = APR_MD5_DIGESTSIZE; rv = apr_file_read(fp, digest, &ds); if ((rv == APR_SUCCESS || rv == APR_EOF) && ds == APR_MD5_DIGESTSIZE) { rv = APR_SUCCESS; apr_md5(digest2, ptr, nbytes); if (memcmp(digest, digest2, APR_MD5_DIGESTSIZE)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02551) "bad md5 match"); rv = APR_EGENERAL; } } } else { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(02552) "at EOF... bypassing md5 match check (old persist file?)"); } } else if (nbytes != size) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(02553) "Expected %" APR_SIZE_T_FMT ": Read %" APR_SIZE_T_FMT, size, nbytes); rv = APR_EGENERAL; } apr_file_close(fp); } } return rv; }
apr_status_t h2_request_add_header(h2_request *req, apr_pool_t *pool, const char *name, size_t nlen, const char *value, size_t vlen) { apr_status_t status = APR_SUCCESS; if (nlen <= 0) { return status; } if (name[0] == ':') { /* pseudo header, see ch. 8.1.2.3, always should come first */ if (!apr_is_empty_table(req->headers)) { ap_log_perror(APLOG_MARK, APLOG_ERR, 0, pool, APLOGNO(02917) "h2_request(%d): pseudo header after request start", req->id); return APR_EGENERAL; } if (H2_HEADER_METHOD_LEN == nlen && !strncmp(H2_HEADER_METHOD, name, nlen)) { req->method = apr_pstrndup(pool, value, vlen); } else if (H2_HEADER_SCHEME_LEN == nlen && !strncmp(H2_HEADER_SCHEME, name, nlen)) { req->scheme = apr_pstrndup(pool, value, vlen); } else if (H2_HEADER_PATH_LEN == nlen && !strncmp(H2_HEADER_PATH, name, nlen)) { req->path = apr_pstrndup(pool, value, vlen); } else if (H2_HEADER_AUTH_LEN == nlen && !strncmp(H2_HEADER_AUTH, name, nlen)) { req->authority = apr_pstrndup(pool, value, vlen); } else { char buffer[32]; memset(buffer, 0, 32); strncpy(buffer, name, (nlen > 31)? 31 : nlen); ap_log_perror(APLOG_MARK, APLOG_WARNING, 0, pool, APLOGNO(02954) "h2_request(%d): ignoring unknown pseudo header %s", req->id, buffer); } } else { /* non-pseudo header, append to work bucket of stream */ status = add_h1_header(req, pool, name, nlen, value, vlen); } return status; }
static char *authz_owner_get_file_group(request_rec *r) { /* file-group only figures out the file's group and lets * other modules do the actual authorization (against a group file/db). * Thus, these modules have to hook themselves after * mod_authz_owner and of course recognize 'file-group', too. */ #if !APR_HAS_USER return NULL; #else /* APR_HAS_USER */ char *reason = NULL; char *group = NULL; apr_finfo_t finfo; apr_status_t status = 0; if (!r->filename) { reason = "no filename available"; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01638) "Authorization of user %s to access %s failed, reason: %s", r->user, r->uri, reason ? reason : "unknown"); return NULL; } status = apr_stat(&finfo, r->filename, APR_FINFO_GROUP, r->pool); if (status != APR_SUCCESS) { reason = apr_pstrcat(r->pool, "could not stat file ", r->filename, NULL); ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01639) "Authorization of user %s to access %s failed, reason: %s", r->user, r->uri, reason ? reason : "unknown"); return NULL; } if (!(finfo.valid & APR_FINFO_GROUP)) { reason = "no file group information available"; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01640) "Authorization of user %s to access %s failed, reason: %s", r->user, r->uri, reason ? reason : "unknown"); return NULL; } status = apr_gid_name_get(&group, finfo.group, r->pool); if (status != APR_SUCCESS || !group) { reason = "could not get name of file group"; ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01641) "Authorization of user %s to access %s failed, reason: %s", r->user, r->uri, reason ? reason : "unknown"); return NULL; } return group; #endif /* APR_HAS_USER */ }
static int authz_dbd_group_query(request_rec *r, authz_dbd_cfg *cfg, apr_array_header_t *groups) { /* SELECT group FROM authz WHERE user = %s */ int rv; const char *message; ap_dbd_t *dbd = dbd_handle(r); apr_dbd_prepared_t *query; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; const char **group; if (cfg->query == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01649) "No query configured for dbd-group!"); return HTTP_INTERNAL_SERVER_ERROR; } query = apr_hash_get(dbd->prepared, cfg->query, APR_HASH_KEY_STRING); if (query == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01650) "Error retrieving query for dbd-group!"); return HTTP_INTERNAL_SERVER_ERROR; } rv = apr_dbd_pvselect(dbd->driver, r->pool, dbd->handle, &res, query, 0, r->user, NULL); if (rv == 0) { for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); rv != -1; rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { if (rv == 0) { group = apr_array_push(groups); *group = apr_dbd_get_entry(dbd->driver, row, 0); } else { message = apr_dbd_error(dbd->driver, dbd->handle, rv); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01651) "authz_dbd in get_row; group query for user=%s [%s]", r->user, message?message:noerror); return HTTP_INTERNAL_SERVER_ERROR; } } } else { message = apr_dbd_error(dbd->driver, dbd->handle, rv); ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01652) "authz_dbd, in groups query for %s [%s]", r->user, message?message:noerror); return HTTP_INTERNAL_SERVER_ERROR; } return OK; }
/** * Load the session by the key specified. */ static apr_status_t dbd_load(request_rec * r, const char *key, const char **val) { apr_status_t rv; ap_dbd_t *dbd = NULL; apr_dbd_prepared_t *statement = NULL; apr_dbd_results_t *res = NULL; apr_dbd_row_t *row = NULL; apr_int64_t expiry = (apr_int64_t) apr_time_now(); session_dbd_dir_conf *conf = ap_get_module_config(r->per_dir_config, &session_dbd_module); if (conf->selectlabel == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01853) "no SessionDBDselectlabel has been specified"); return APR_EGENERAL; } rv = dbd_init(r, conf->selectlabel, &dbd, &statement); if (rv) { return rv; } rv = apr_dbd_pvbselect(dbd->driver, r->pool, dbd->handle, &res, statement, 0, key, &expiry, NULL); if (rv) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01854) "query execution error saving session '%s' " "in database using query '%s': %s", key, conf->selectlabel, apr_dbd_error(dbd->driver, dbd->handle, rv)); return APR_EGENERAL; } for (rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1); rv != -1; rv = apr_dbd_get_row(dbd->driver, r->pool, res, &row, -1)) { if (rv != 0) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01855) "error retrieving results while saving '%s' " "in database using query '%s': %s", key, conf->selectlabel, apr_dbd_error(dbd->driver, dbd->handle, rv)); return APR_EGENERAL; } if (*val == NULL) { *val = apr_dbd_get_entry(dbd->driver, row, 0); } /* we can't break out here or row won't get cleaned up */ } return APR_SUCCESS; }
/** * Initialise the encryption as per the current config. * * Returns APR_SUCCESS if successful. */ static apr_status_t crypt_init(request_rec *r, const apr_crypto_t *f, apr_crypto_block_key_type_e **cipher, session_crypto_dir_conf * dconf) { apr_status_t res; apr_hash_t *ciphers; res = apr_crypto_get_block_key_types(&ciphers, f); if (APR_SUCCESS != res) { ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, APLOGNO(01823) "no ciphers returned by APR. " "session encryption not possible"); return res; } *cipher = apr_hash_get(ciphers, dconf->cipher, APR_HASH_KEY_STRING); if (!(*cipher)) { apr_hash_index_t *hi; const void *key; apr_ssize_t klen; int sum = 0; int offset = 0; char *options = NULL; for (hi = apr_hash_first(r->pool, ciphers); hi; hi = apr_hash_next(hi)) { apr_hash_this(hi, NULL, &klen, NULL); sum += klen + 2; } for (hi = apr_hash_first(r->pool, ciphers); hi; hi = apr_hash_next(hi)) { apr_hash_this(hi, &key, &klen, NULL); if (!options) { options = apr_palloc(r->pool, sum + 1); } else { options[offset++] = ','; options[offset++] = ' '; } strncpy(options + offset, key, klen); offset += klen; } options[offset] = 0; ap_log_rerror(APLOG_MARK, APLOG_ERR, res, r, APLOGNO(01824) "cipher '%s' not recognised by crypto driver. " "session encryption not possible, options: %s", dconf->cipher, options); return APR_EGENERAL; } return APR_SUCCESS; }
/* ToDo: This function should be made to handle setting up * a scoreboard shared between processes using any IPC technique, * not just a shared memory segment */ static apr_status_t open_scoreboard(apr_pool_t *pconf) { #if APR_HAS_SHARED_MEMORY apr_status_t rv; char *fname = NULL; apr_pool_t *global_pool; /* We don't want to have to recreate the scoreboard after * restarts, so we'll create a global pool and never clean it. */ rv = apr_pool_create(&global_pool, NULL); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00002) "Fatal error: unable to create global pool " "for use by the scoreboard"); return rv; } /* The config says to create a name-based shmem */ if (ap_scoreboard_fname) { /* make sure it's an absolute pathname */ fname = ap_server_root_relative(pconf, ap_scoreboard_fname); if (!fname) { ap_log_error(APLOG_MARK, APLOG_CRIT, APR_EBADPATH, ap_server_conf, APLOGNO(00003) "Fatal error: Invalid Scoreboard path %s", ap_scoreboard_fname); return APR_EBADPATH; } return create_namebased_scoreboard(global_pool, fname); } else { /* config didn't specify, we get to choose shmem type */ rv = apr_shm_create(&ap_scoreboard_shm, scoreboard_size, NULL, global_pool); /* anonymous shared memory */ if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, ap_server_conf, APLOGNO(00004) "Unable to create or access scoreboard " "(anonymous shared memory failure)"); return rv; } /* Make up a filename and do name-based shmem */ else if (rv == APR_ENOTIMPL) { /* Make sure it's an absolute pathname */ ap_scoreboard_fname = DEFAULT_SCOREBOARD; fname = ap_server_root_relative(pconf, ap_scoreboard_fname); return create_namebased_scoreboard(global_pool, fname); } } #endif /* APR_HAS_SHARED_MEMORY */ return APR_SUCCESS; }
static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb) { request_rec *r = f->r; ef_ctx_t *ctx = f->ctx; apr_status_t rv; if (!ctx) { if ((rv = init_filter_instance(f)) != APR_SUCCESS) { ctx = f->ctx; ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01467) "can't initialise output filter %s: %s", f->frec->name, (ctx->dc->onfail == 1) ? "removing" : "aborting"); ap_remove_output_filter(f); if (ctx->dc->onfail == 1) { return ap_pass_brigade(f->next, bb); } else { apr_bucket *e; f->r->status_line = "500 Internal Server Error"; apr_brigade_cleanup(bb); e = ap_bucket_error_create(HTTP_INTERNAL_SERVER_ERROR, NULL, r->pool, f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); e = apr_bucket_eos_create(f->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); ap_pass_brigade(f->next, bb); return AP_FILTER_ERROR; } } ctx = f->ctx; } if (ctx->noop) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } rv = ef_unified_filter(f, bb); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01468) "ef_unified_filter() failed"); } if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(01469) "ap_pass_brigade() failed"); } return rv; }
apr_status_t ssl_die(server_rec *s) { if (s != NULL && s->is_virtual && s->error_fname != NULL) ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02311) "Fatal error initialising mod_ssl, exiting. " "See %s for more information", ap_server_root_relative(s->process->pool, s->error_fname)); else ap_log_error(APLOG_MARK, APLOG_EMERG, 0, NULL, APLOGNO(02312) "Fatal error initialising mod_ssl, exiting."); return APR_EGENERAL; }
static int proxy_wstunnel_transfer(request_rec *r, conn_rec *c_i, conn_rec *c_o, apr_bucket_brigade *bb, char *name) { int rv; #ifdef DEBUGGING apr_off_t len; #endif do { apr_brigade_cleanup(bb); rv = ap_get_brigade(c_i->input_filters, bb, AP_MODE_READBYTES, APR_NONBLOCK_READ, AP_IOBUFSIZE); if (rv == APR_SUCCESS) { if (c_o->aborted) { return APR_EPIPE; } if (APR_BRIGADE_EMPTY(bb)) { break; } #ifdef DEBUGGING len = -1; apr_brigade_length(bb, 0, &len); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02440) "read %" APR_OFF_T_FMT " bytes from %s", len, name); #endif rv = ap_pass_brigade(c_o->output_filters, bb); if (rv == APR_SUCCESS) { ap_fflush(c_o->output_filters, bb); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02441) "error on %s - ap_pass_brigade", name); } } else if (!APR_STATUS_IS_EAGAIN(rv) && !APR_STATUS_IS_EOF(rv)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(02442) "error on %s - ap_get_brigade", name); } } while (rv == APR_SUCCESS); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, rv, r, "wstunnel_transfer complete"); if (APR_STATUS_IS_EAGAIN(rv)) { rv = APR_SUCCESS; } return rv; }
static apr_status_t include_cmd(include_ctx_t *ctx, ap_filter_t *f, apr_bucket_brigade *bb, const char *command) { cgi_exec_info_t e_info; const char **argv; apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL; apr_status_t rv; request_rec *r = f->r; add_ssi_vars(r); e_info.process_cgi = 0; e_info.cmd_type = APR_SHELLCMD; e_info.detached = 0; e_info.in_pipe = APR_NO_PIPE; e_info.out_pipe = APR_FULL_BLOCK; e_info.err_pipe = APR_NO_PIPE; e_info.prog_type = RUN_AS_SSI; e_info.bb = &bb; e_info.ctx = ctx; e_info.next = f->next; e_info.addrspace = 0; if ((rv = cgi_build_command(&command, &argv, r, r->pool, &e_info)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01226) "don't know how to spawn cmd child process: %s", r->filename); return rv; } /* run the script in its own process */ if ((rv = run_cgi_child(&script_out, &script_in, &script_err, command, argv, r, r->pool, &e_info)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01227) "couldn't spawn child process: %s", r->filename); return rv; } APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pipe_create(script_in, f->c->bucket_alloc)); ctx->flush_now = 1; /* We can't close the pipe here, because we may return before the * full CGI has been sent to the network. That's okay though, * because we can rely on the pool to close the pipe for us. */ return APR_SUCCESS; }
int checkLastFromFiles(request_rec * r, const char * filter, const char * packet) { BLOOM * bloom; FILE * fp = fopen(filter, "r"); size_t read; /* read the filter size */ size_t size; read = fread(&size, sizeof(size_t), 1, fp); /* Re-create the filter */ if(!(bloom=bloom_create(size, 2, sax_hash, sdbm_hash))) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(05011) "check last: bloom filter"); /* Read the filter from file */ read = fread(bloom->a, sizeof(char), (bloom->asize+CHAR_BIT-1)/CHAR_BIT, fp); fclose(fp); fp = fopen(packet, "r"); /* Read len of the packet */ int buflen; read = fread(&buflen, sizeof(int), 1, fp); /* Alocate memory for the buffer */ char * buffer; if((buffer = (char *) malloc(buflen * sizeof(char))) == NULL) ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(05011) "check last: buffer"); /* Read the buffer */ read = fread(buffer, sizeof(char), buflen, fp); fclose(fp); /* Check and return if the request was received */ if(bloom_check(bloom, buffer)){ free(buffer); bloom_destroy(bloom); return 1; } else{ free(buffer); bloom_destroy(bloom); return 0; } }
/* Create a CGI bucket using pipes from script stdout 'out' * and stderr 'err', for request 'r'. */ static apr_bucket *cgi_bucket_create(request_rec *r, apr_file_t *out, apr_file_t *err, apr_bucket_alloc_t *list) { apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); apr_status_t rv; apr_pollfd_t fd; struct cgi_bucket_data *data = apr_palloc(r->pool, sizeof *data); APR_BUCKET_INIT(b); b->free = apr_bucket_free; b->list = list; b->type = &bucket_type_cgi; b->length = (apr_size_t)(-1); b->start = -1; /* Create the pollset */ rv = apr_pollset_create(&data->pollset, 2, r->pool, 0); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01217) "apr_pollset_create(); check system or user limits"); return NULL; } fd.desc_type = APR_POLL_FILE; fd.reqevents = APR_POLLIN; fd.p = r->pool; fd.desc.f = out; /* script's stdout */ fd.client_data = (void *)1; rv = apr_pollset_add(data->pollset, &fd); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01218) "apr_pollset_add(); check system or user limits"); return NULL; } fd.desc.f = err; /* script's stderr */ fd.client_data = (void *)2; rv = apr_pollset_add(data->pollset, &fd); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01219) "apr_pollset_add(); check system or user limits"); return NULL; } data->r = r; b->data = data; return b; }
STACK_OF(X509) *ssl_read_pkcs7(server_rec *s, const char *pkcs7) { PKCS7 *p7; STACK_OF(X509) *certs = NULL; FILE *f; f = fopen(pkcs7, "r"); if (!f) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02212) "Can't open %s", pkcs7); ssl_die(s); } p7 = PEM_read_PKCS7(f, NULL, NULL, NULL); if (!p7) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02274) "Can't read PKCS7 object %s", pkcs7); ssl_log_ssl_error(SSLLOG_MARK, APLOG_CRIT, s); exit(1); } switch (OBJ_obj2nid(p7->type)) { case NID_pkcs7_signed: certs = p7->d.sign->cert; p7->d.sign->cert = NULL; PKCS7_free(p7); break; case NID_pkcs7_signedAndEnveloped: certs = p7->d.signed_and_enveloped->cert; p7->d.signed_and_enveloped->cert = NULL; PKCS7_free(p7); break; default: ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02213) "Don't understand PKCS7 file %s", pkcs7); ssl_die(s); } if (!certs) { ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, APLOGNO(02214) "No certificates in %s", pkcs7); ssl_die(s); } fclose(f); return certs; }
static int simple_pre_config(apr_pool_t * pconf, apr_pool_t * plog, apr_pool_t * ptemp) { int run_debug; apr_status_t rv; simple_core_t *sc; /* this is our first 'real' entry point, so setup everything here. */ rv = simple_core_init_once(); if (rv) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00257) "simple_core_init_once: Fatal Error Encountered"); return HTTP_INTERNAL_SERVER_ERROR; } sc = simple_core_get(); sc->restart_num++; run_debug = ap_exists_config_define("DEBUG"); if (run_debug) { sc->run_foreground = 1; sc->run_single_process = 1; } else { sc->run_foreground = ap_exists_config_define("FOREGROUND"); } if (sc->restart_num == 2) { if (sc->run_foreground) { rv = apr_proc_detach(APR_PROC_DETACH_FOREGROUND); } else { rv = apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); } if (rv) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, NULL, APLOGNO(00258) "simple_pre_config: apr_proc_detach(%s) failed", sc->run_foreground ? "FOREGROUND" : "DAEMONIZE"); return HTTP_INTERNAL_SERVER_ERROR; } } return OK; }
/** * Read a cookie called name, placing its value in val. * * Both the Cookie and Cookie2 headers are scanned for the cookie. * * If the cookie is duplicated, this function returns APR_EGENERAL. If found, * and if remove is non zero, the cookie will be removed from the headers, and * thus kept private from the backend. */ AP_DECLARE(apr_status_t) ap_cookie_read(request_rec * r, const char *name, const char **val, int remove) { ap_cookie_do v; v.r = r; v.encoded = NULL; v.new_cookies = apr_table_make(r->pool, 10); v.duplicated = 0; v.name = name; apr_table_do((int (*) (void *, const char *, const char *)) extract_cookie_line, (void *) &v, r->headers_in, "Cookie", "Cookie2", NULL); if (v.duplicated) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00011) LOG_PREFIX "client submitted cookie '%s' more than once: %s", v.name, r->uri); return APR_EGENERAL; } /* remove our cookie(s), and replace them */ if (remove) { apr_table_unset(r->headers_in, "Cookie"); apr_table_unset(r->headers_in, "Cookie2"); r->headers_in = apr_table_overlay(r->pool, r->headers_in, v.new_cookies); } *val = v.encoded; return APR_SUCCESS; }
/** * Write an RFC2965 compliant cookie. * * @param r The request * @param name2 The name of the cookie. * @param val The value to place in the cookie. * @param attrs2 The string containing additional cookie attributes. If NULL, the * DEFAULT_ATTRS will be used. * @param maxage If non zero, a Max-Age header will be added to the cookie. */ AP_DECLARE(apr_status_t) ap_cookie_write2(request_rec * r, const char *name2, const char *val, const char *attrs2, long maxage, ...) { const char *buffer; const char *rfc2965; apr_table_t *t; va_list vp; /* handle expiry */ buffer = ""; if (maxage) { buffer = apr_pstrcat(r->pool, "Max-Age=", apr_ltoa(r->pool, maxage), ";", NULL); } /* create RFC2965 compliant cookie */ rfc2965 = apr_pstrcat(r->pool, name2, "=", val, ";", buffer, attrs2 && *attrs2 ? attrs2 : DEFAULT_ATTRS, NULL); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00008) LOG_PREFIX "user '%s' set cookie2: '%s'", r->user, rfc2965); /* write the cookie to the header table(s) provided */ va_start(vp, maxage); while ((t = va_arg(vp, apr_table_t *))) { apr_table_addn(t, SET_COOKIE2, rfc2965); } va_end(vp); return APR_SUCCESS; }
BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, apr_time_t expiry, SSL_SESSION *sess, apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); unsigned char encoded[SSL_SESSION_MAX_DER], *ptr; unsigned int len; apr_status_t rv; /* Serialise the session. */ len = i2d_SSL_SESSION(sess, NULL); if (len > sizeof encoded) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01875) "session is too big (%u bytes)", len); return FALSE; } ptr = encoded; len = i2d_SSL_SESSION(sess, &ptr); if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { ssl_mutex_on(s); } rv = mc->sesscache->store(mc->sesscache_context, s, id, idlen, expiry, encoded, len, p); if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) { ssl_mutex_off(s); } return rv == APR_SUCCESS ? TRUE : FALSE; }
static int am_check_access(request_rec *r) { int method = r->method_number; am_conf_t *conf; conf = (am_conf_t *) ap_get_module_config(r->per_dir_config, &allowmethods_module); if (!conf || conf->allowed == 0) { return DECLINED; } r->allowed = conf->allowed; if (conf->allowed & (AP_METHOD_BIT << method)) { return DECLINED; } ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01623) "client method denied by server configuration: '%s' to %s%s", r->method, r->filename ? "" : "uri ", r->filename ? r->filename : r->uri); return HTTP_METHOD_NOT_ALLOWED; }
/* * delete all URL entities from the cache * */ int cache_remove_url(cache_request_rec *cache, request_rec *r) { cache_provider_list *list; cache_handle_t *h; list = cache->providers; /* Remove the stale cache entry if present. If not, we're * being called from outside of a request; remove the * non-stale handle. */ h = cache->stale_handle ? cache->stale_handle : cache->handle; if (!h) { return OK; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00691) "cache: Removing url %s from the cache", h->cache_obj->key); /* for each specified cache type, delete the URL */ while(list) { list->provider->remove_url(h, r); list = list->next; } return OK; }
/* should be apr_status_t really */ static void restore_slotmem(void *ptr, const char *name, apr_size_t size, apr_pool_t *pool) { const char *storename; apr_file_t *fp; apr_size_t nbytes = size; apr_status_t rv; storename = slotmem_filename(pool, name, 1); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02335) "restoring %s", storename); if (storename) { rv = apr_file_open(&fp, storename, APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); if (rv == APR_SUCCESS) { apr_finfo_t fi; if (apr_file_info_get(&fi, APR_FINFO_SIZE, fp) == APR_SUCCESS) { if (fi.size == nbytes) { apr_file_read(fp, ptr, &nbytes); } else { apr_file_close(fp); apr_file_remove(storename, pool); return; } } apr_file_close(fp); } } }
/* BS2000 requires a "special" version of fork() before a setuid() call */ pid_t os_fork(const char *user) { pid_t pid; char username[USER_LEN+1]; switch (os_forktype(0)) { case bs2_FORK: pid = fork(); break; case bs2_UFORK: apr_cpystrn(username, user, sizeof username); /* Make user name all upper case - for some versions of ufork() */ ap_str_toupper(username); pid = ufork(username); if (pid == -1 && errno == EPERM) { ap_log_error(APLOG_MARK, APLOG_EMERG, errno, ap_server_conf, APLOGNO(02181) "ufork: Possible mis-configuration " "for user %s - Aborting.", user); exit(1); } break; default: pid = 0; break; } return pid; }
static int stream_open(h2_session *session, int stream_id) { h2_stream * stream; if (session->aborted) { return NGHTTP2_ERR_CALLBACK_FAILURE; } stream = h2_mplx_open_io(session->mplx, stream_id); if (stream) { h2_stream_set_add(session->streams, stream); if (stream->id > session->max_stream_received) { session->max_stream_received = stream->id; } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_session: stream(%ld-%d): opened", session->id, stream_id); return 0; } ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, session->c, APLOGNO(02918) "h2_session: stream(%ld-%d): unable to create", session->id, stream_id); return NGHTTP2_ERR_INVALID_STREAM_ID; }
static int on_header_cb(nghttp2_session *ngh2, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags, void *userp) { h2_session *session = (h2_session *)userp; h2_stream * stream; apr_status_t status; (void)ngh2; (void)flags; if (session->aborted) { return NGHTTP2_ERR_CALLBACK_FAILURE; } stream = h2_stream_set_get(session->streams, frame->hd.stream_id); if (!stream) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02920) "h2_session: stream(%ld-%d): on_header for unknown stream", session->id, (int)frame->hd.stream_id); return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } status = h2_stream_write_header(stream, (const char *)name, namelen, (const char *)value, valuelen); if (status != APR_SUCCESS) { return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; } return 0; }
/* Start submitting the response to a stream request. This is possible * once we have all the response headers. The response body will be * read by the session using the callback we supply. */ apr_status_t h2_session_handle_response(h2_session *session, h2_stream *stream) { apr_status_t status = APR_SUCCESS; int rv = 0; AP_DEBUG_ASSERT(session); AP_DEBUG_ASSERT(stream); AP_DEBUG_ASSERT(stream->response); if (stream->response->ngheader) { rv = submit_response(session, stream->response); } else { rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, stream->id, NGHTTP2_PROTOCOL_ERROR); } if (nghttp2_is_fatal(rv)) { status = APR_EGENERAL; h2_session_abort_int(session, rv); ap_log_cerror(APLOG_MARK, APLOG_ERR, status, session->c, APLOGNO(02940) "submit_response: %s", nghttp2_strerror(rv)); } return status; }
static int submit_response(h2_session *session, h2_response *response) { nghttp2_data_provider provider; int rv; memset(&provider, 0, sizeof(provider)); provider.source.fd = response->stream_id; provider.read_callback = stream_data_cb; ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "h2_stream(%ld-%d): submitting response %s", session->id, response->stream_id, response->status); rv = nghttp2_submit_response(session->ngh2, response->stream_id, response->ngheader->nv, response->ngheader->nvlen, &provider); if (rv != 0) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c, APLOGNO(02939) "h2_stream(%ld-%d): submit_response: %s", session->id, response->stream_id, nghttp2_strerror(rv)); } else { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "h2_stream(%ld-%d): submitted response %s, rv=%d", session->id, response->stream_id, response->status, rv); } return rv; }
static apr_table_t *parse_headers(apr_array_header_t *hlines, apr_pool_t *pool) { if (hlines) { apr_table_t *headers = apr_table_make(pool, hlines->nelts); int i; for (i = 0; i < hlines->nelts; ++i) { char *hline = ((char **)hlines->elts)[i]; char *sep = ap_strchr(hline, ':'); if (!sep) { ap_log_perror(APLOG_MARK, APLOG_WARNING, APR_EINVAL, pool, APLOGNO(02955) "h2_response: invalid header[%d] '%s'", i, (char*)hline); /* not valid format, abort */ return NULL; } (*sep++) = '\0'; while (*sep == ' ' || *sep == '\t') { ++sep; } if (!h2_util_ignore_header(hline)) { apr_table_merge(headers, hline, sep); } } return headers; } else { return apr_table_make(pool, 0); } }
/* handle all varieties of core dumping signals */ static void sig_coredump(int sig) { apr_filepath_set(ap_coredump_dir, pconf); apr_signal(sig, SIG_DFL); #if AP_ENABLE_EXCEPTION_HOOK run_fatal_exception_hook(sig); #endif /* linuxthreads issue calling getpid() here: * This comparison won't match if the crashing thread is * some module's thread that runs in the parent process. * The fallout, which is limited to linuxthreads: * The special log message won't be written when such a * thread in the parent causes the parent to crash. */ if (getpid() == parent_pid) { ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00060) "seg fault or similar nasty error detected " "in the parent process"); /* XXX we can probably add some rudimentary cleanup code here, * like getting rid of the pid file. If any additional bad stuff * happens, we are protected from recursive errors taking down the * system since this function is no longer the signal handler GLA */ } kill(getpid(), sig); /* At this point we've got sig blocked, because we're still inside * the signal handler. When we leave the signal handler it will * be unblocked, and we'll take the signal... and coredump or whatever * is appropriate for this particular Unix. In addition the parent * will see the real signal we received -- whereas if we called * abort() here, the parent would only see SIGABRT. */ }