static void putline(apr_file_t *f, char *l) { int x; for (x = 0; l[x]; x++) apr_file_putc(l[x], f); }
/* Create FNAME with global `lines' as initial data. Use EOL_STR as * the end-of-line marker between lines, or if EOL_STR is NULL, choose * a random marker at each opportunity. Use POOL for any temporary * allocation. */ static svn_error_t * create_file(const char *fname, const char *eol_str, apr_pool_t *pool) { apr_status_t apr_err; apr_file_t *f; apr_size_t i, j; apr_err = apr_file_open(&f, fname, (APR_WRITE | APR_CREATE | APR_EXCL | APR_BINARY), APR_OS_DEFAULT, pool); if (apr_err) return svn_error_create(apr_err, NULL, fname); for (i = 0; i < (sizeof(lines) / sizeof(*lines)); i++) { const char *this_eol_str = eol_str ? eol_str : random_eol_marker(); apr_err = apr_file_printf(f, "%s", lines[i]); /* Is it overly paranoid to use putc(), because of worry about fprintf() doing a newline conversion? */ for (j = 0; this_eol_str[j]; j++) { apr_err = apr_file_putc(this_eol_str[j], f); if (apr_err) return svn_error_create(apr_err, NULL, fname); } } apr_err = apr_file_close(f); if (apr_err) return svn_error_create(apr_err, NULL, fname); return SVN_NO_ERROR; }
APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) { if (pollset->flags & APR_POLLSET_WAKEABLE) return apr_file_putc(1, pollset->wakeup_pipe[1]); else return APR_EINIT; }
static void create_testfile(apr_pool_t *p, const char *fname) { apr_file_t *f = NULL; apr_status_t rv; char buf[120]; int i; apr_finfo_t finfo; printf("Creating a test file...\n"); rv = apr_file_open(&f, fname, APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE | APR_FOPEN_BUFFERED, APR_UREAD | APR_UWRITE, p); if (rv) { aprerr("apr_file_open()", rv); } buf[0] = FILE_DATA_CHAR; buf[1] = '\0'; for (i = 0; i < FILE_LENGTH; i++) { /* exercise apr_file_putc() and apr_file_puts() on buffered files */ if ((i % 2) == 0) { rv = apr_file_putc(buf[0], f); if (rv) { aprerr("apr_file_putc()", rv); } } else { rv = apr_file_puts(buf, f); if (rv) { aprerr("apr_file_puts()", rv); } } } rv = apr_file_close(f); if (rv) { aprerr("apr_file_close()", rv); } rv = apr_stat(&finfo, fname, APR_FINFO_NORM, p); if (rv != APR_SUCCESS && ! APR_STATUS_IS_INCOMPLETE(rv)) { aprerr("apr_stat()", rv); } if (finfo.size != FILE_LENGTH) { fprintf(stderr, "test file %s should be %ld-bytes long\n" "instead it is %ld-bytes long\n", fname, (long int)FILE_LENGTH, (long int)finfo.size); exit(1); } }
/* Try to open a temporary file in the temporary dir, write to it, and then close it. */ static int test_tempdir(const char *temp_dir, apr_pool_t *p) { apr_file_t *dummy_file; const char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL); if (apr_file_mktemp(&dummy_file, (char *)path, 0, p) == APR_SUCCESS) { if (apr_file_putc('!', dummy_file) == APR_SUCCESS) { if (apr_file_close(dummy_file) == APR_SUCCESS) { return 1; } } } return 0; }
/* Try to open a temporary file in the temporary dir, write to it, and then close it. */ static int Fixed_test_tempdir(const char *temp_dir, apr_pool_t *p) { apr_file_t *dummy_file; // This is the only actual fix - adding the ".XXXXXX"! const char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL); if (apr_file_mktemp(&dummy_file, (char *)path, 0, p) == APR_SUCCESS) { if (apr_file_putc('!', dummy_file) == APR_SUCCESS) { if (apr_file_close(dummy_file) == APR_SUCCESS) { apr_file_remove(path, p); return 1; } } } return 0; }
/** Interrupt the blocked poll call */ APT_DECLARE(apt_bool_t) apt_pollset_wakeup(apt_pollset_t *pollset) { apt_bool_t status = TRUE; #ifdef WIN32 char tmp = 0; apr_size_t len = sizeof(tmp); if(apr_socket_send(pollset->wakeup_pipe[1],&tmp,&len) != APR_SUCCESS) { status = FALSE; } #else if(apr_file_putc(1, pollset->wakeup_pipe[1]) != APR_SUCCESS) { status = FALSE; } #endif return status; }
static apr_status_t at_report_file_write(at_report_t *ctx, const char *msg) { struct at_report_file *r = (struct at_report_file *)ctx; apr_file_t *f = r->file; apr_size_t len = strlen(msg); apr_status_t s; s = apr_file_write_full(f, msg, len, &len); if (s != APR_SUCCESS) return s; s = apr_file_putc('\n', f); if (s != APR_SUCCESS) return s; return apr_file_flush(f); }
zktool_display_options(const apr_getopt_option_t *options, apr_file_t *f, apr_pool_t *pool) { int self_created_pool = 0; const apr_getopt_option_t *opt; const char *optfmt; if(pool == NULL) { pool = zeke_root_subpool_create(); self_created_pool++; } if(f == NULL) { apr_status_t st; if((f = zstdout) == NULL && (f = zstderr) == NULL) { st = apr_file_open_stderr(&f,pool); if(st != APR_SUCCESS) { st = apr_file_open_stdout(&f,pool); if(st != APR_SUCCESS) return; } apr_file_inherit_unset(f); } } for(opt = options; opt->name != NULL || opt->optch != 0; opt++) { optfmt = zktool_format_opt(opt,NULL,pool); assert(optfmt != NULL); #if 0 optfmt = apr_pstrcat(pool,optfmt,apr_psprintf(pool,"%%%ds%%s\n",(int)(30-strlen(optfmt))),NULL); #endif apr_file_printf(f,optfmt,opt->description); apr_file_putc('\n',f); } if(self_created_pool) apr_pool_destroy(pool); }
/* Run an external authentication program using the given method for passing * in the data. The login name is always passed in. Dataname is "GROUP" or * "PASS" and data is the group list or password being checked. To launch * a detached daemon, run this with extmethod=NULL. * * If the authenticator was run, we return the numeric code from the * authenticator, normally 0 if the login was valid, some small positive * number if not. If we were not able to run the authenticator, we log * an error message and return a numeric error code: * * -1 Could not execute authenticator, usually a path or permission problem * -2 The external authenticator crashed or was killed. * -3 Could not create process attribute structure * -4 apr_proc_wait() did not return a status code. Should never happen. * -5 apr_proc_wait() returned before child finished. Should never happen. */ static int exec_external(const char *extpath, const char *extmethod, const request_rec *r, const char *dataname, const char *data) { conn_rec *c= r->connection; apr_pool_t *p= r->pool; int isdaemon, usecheck= 0, usepipeout= 0, usepipein= 0; apr_procattr_t *procattr; apr_proc_t proc; apr_status_t rc= APR_SUCCESS; char *child_env[12]; char *child_arg[MAX_ARG+2]; const char *t; int i, status= -4; apr_exit_why_e why= APR_PROC_EXIT; apr_sigfunc_t *sigchld; /* Set various flags based on the execution method */ isdaemon= (extmethod == NULL); if (!isdaemon) { usecheck= extmethod && !strcasecmp(extmethod, "checkpassword"); usepipeout= usecheck || (extmethod && !strcasecmp(extmethod, "pipes")); usepipein= usepipeout || (extmethod && !strcasecmp(extmethod, "pipe")); } /* Create the environment for the child. Daemons don't get these, they * just inherit apache's environment variables. */ if (!isdaemon) { const char *cookie, *host, *remote_host; authnz_external_dir_config_rec *dir= (authnz_external_dir_config_rec *) ap_get_module_config(r->per_dir_config, &authnz_external_module); i= 0; if (!usepipein) { /* Put user name and password/group into environment */ child_env[i++]= apr_pstrcat(p, ENV_USER"=", r->user, NULL); child_env[i++]= apr_pstrcat(p, dataname, "=", data, NULL); } child_env[i++]= apr_pstrcat(p, "PATH=", getenv("PATH"), NULL); child_env[i++]= apr_pstrcat(p, "AUTHTYPE=", dataname, NULL); remote_host= ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST,NULL); if (remote_host != NULL) child_env[i++]= apr_pstrcat(p, ENV_HOST"=", remote_host,NULL); if (r->useragent_ip) child_env[i++]= apr_pstrcat(p, ENV_IP"=", r->useragent_ip, NULL); if (r->uri) child_env[i++]= apr_pstrcat(p, ENV_URI"=", r->uri, NULL); if ((host= apr_table_get(r->headers_in, "Host")) != NULL) child_env[i++]= apr_pstrcat(p, ENV_HTTP_HOST"=", host, NULL); if (dir->context) child_env[i++]= apr_pstrcat(r->pool, ENV_CONTEXT"=", dir->context, NULL); #ifdef ENV_COOKIE if ((cookie= apr_table_get(r->headers_in, "Cookie")) != NULL) child_env[i++]= apr_pstrcat(p, ENV_COOKIE"=", cookie, NULL); #endif /* NOTE: If you add environment variables, * remember to increase the size of the child_env[] array */ /* End of environment */ child_env[i]= NULL; } /* Construct argument array */ for (t= extpath, i=0; *t != '\0' && (i <= MAX_ARG + 1); child_arg[i++]= ap_getword_white(p, &t)) {} child_arg[i]= NULL; /* Create the process attribute structure describing the script we * want to run using the Thread/Process functions from the Apache * portable runtime library. */ if (((rc= apr_procattr_create(&procattr, p)) != APR_SUCCESS) || /* should we create pipes to stdin, stdout and stderr? */ ((rc= apr_procattr_io_set(procattr, (usepipein && !usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE, usepipeout ? APR_FULL_BLOCK : APR_NO_PIPE, (usepipein && usecheck) ? APR_FULL_BLOCK : APR_NO_PIPE)) != APR_SUCCESS ) || /* will give full path of program and make a new environment */ ((rc= apr_procattr_cmdtype_set(procattr, isdaemon ? APR_PROGRAM_ENV : APR_PROGRAM)) != APR_SUCCESS) || /* detach the child only if it is a daemon */ ((rc= apr_procattr_detach_set(procattr, isdaemon)) != APR_SUCCESS) || /* function to call if child has error after fork, before exec */ ((rc= apr_procattr_child_errfn_set(procattr, extchilderr) != APR_SUCCESS))) { /* Failed. Probably never happens. */ ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "could not set child process attributes"); return -3; } /* Sometimes other modules wil mess up sigchild. Need to fix it for * the wait call to work correctly. */ sigchld= apr_signal(SIGCHLD,SIG_DFL); /* Start the child process */ rc= apr_proc_create(&proc, child_arg[0], (const char * const *)child_arg, (const char * const *)child_env, procattr, p); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "Could not run external authenticator: %d: %s", rc, child_arg[0]); return -1; } if (isdaemon) return 0; apr_pool_note_subprocess(p, &proc, APR_KILL_AFTER_TIMEOUT); if (usepipein) { /* Select appropriate pipe to write to */ apr_file_t *pipe= (usecheck ? proc.err : proc.in); /* Send the user */ apr_file_write_full(pipe, r->user, strlen(r->user), NULL); apr_file_putc(usecheck ? '\0' : '\n', pipe); /* Send the password */ apr_file_write_full(pipe, data, strlen(data), NULL); apr_file_putc(usecheck ? '\0' : '\n', pipe); /* Send the uri/path */ apr_file_write_full(pipe, r->uri, strlen(r->uri), NULL); apr_file_putc(usecheck ? '\0' : '\n', pipe); /* Send dummy timestamp for checkpassword */ if (usecheck) apr_file_write_full(pipe, "0", 2, NULL); /* Close the file */ apr_file_close(pipe); } /* Wait for the child process to terminate, and get status */ rc= apr_proc_wait(&proc,&status,&why,APR_WAIT); /* Restore sigchild to whatever it was before we reset it */ apr_signal(SIGCHLD,sigchld); if (!APR_STATUS_IS_CHILD_DONE(rc)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, "Could not get status from child process"); return -5; } if (!APR_PROC_CHECK_EXIT(why)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "External authenticator died on signal %d",status); return -2; } return status; }