Пример #1
0
apr_status_t
serf__spnego_init_sec_context(serf__spnego_context_t *ctx,
                              const char *service,
                              const char *hostname,
                              serf__spnego_buffer_t *input_buf,
                              serf__spnego_buffer_t *output_buf,
                              apr_pool_t *result_pool,
                              apr_pool_t *scratch_pool
                              )
{
    gss_buffer_desc gss_input_buf = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc *gss_output_buf_p;
    OM_uint32 gss_min_stat, gss_maj_stat;
    gss_name_t host_gss_name;
    gss_buffer_desc bufdesc;
    gss_OID dummy; /* unused */

    /* Get the name for the HTTP service at the target host. */
    /* TODO: should be shared between multiple requests. */
    bufdesc.value = apr_pstrcat(scratch_pool, service, "@", hostname, NULL);
    bufdesc.length = strlen(bufdesc.value);
    serf__log(AUTH_VERBOSE, __FILE__, "Get principal for %s\n", bufdesc.value);
    gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc,
                                    GSS_C_NT_HOSTBASED_SERVICE,
                                    &host_gss_name);
    if(GSS_ERROR(gss_maj_stat)) {
        log_error(AUTH_VERBOSE, __FILE__, ctx,
                  gss_maj_stat, gss_min_stat,
                  "Error converting principal name to GSS internal format ");
        return SERF_ERROR_AUTHN_FAILED;
    }

    /* If the server sent us a token, pass it to gss_init_sec_token for
       validation. */
    gss_input_buf.value = input_buf->value;
    gss_input_buf.length = input_buf->length;

    gss_output_buf_p = apr_pcalloc(result_pool, sizeof(*gss_output_buf_p));

    /* Establish a security context to the server. */
    gss_maj_stat = gss_init_sec_context
        (&gss_min_stat,             /* minor_status */
         GSS_C_NO_CREDENTIAL,       /* XXXXX claimant_cred_handle */
         &ctx->gss_ctx,              /* gssapi context handle */
         host_gss_name,             /* [email protected] name */
         ctx->gss_mech,             /* mech_type (SPNEGO) */
         GSS_C_MUTUAL_FLAG,         /* ensure the peer authenticates itself */
         0,                         /* default validity period */
         GSS_C_NO_CHANNEL_BINDINGS, /* do not use channel bindings */
         &gss_input_buf,            /* server token, initially empty */
         &dummy,                    /* actual mech type */
         gss_output_buf_p,           /* output_token */
         NULL,                      /* ret_flags */
         NULL                       /* not interested in remaining validity */
         );

    apr_pool_cleanup_register(result_pool, gss_output_buf_p,
                              cleanup_sec_buffer,
                              apr_pool_cleanup_null);

    output_buf->value = gss_output_buf_p->value;
    output_buf->length = gss_output_buf_p->length;

    switch(gss_maj_stat) {
    case GSS_S_COMPLETE:
        return APR_SUCCESS;
    case GSS_S_CONTINUE_NEEDED:
        return APR_EAGAIN;
    default:
        log_error(AUTH_VERBOSE, __FILE__, ctx,
                  gss_maj_stat, gss_min_stat,
                  "Error during Kerberos handshake");
        return SERF_ERROR_AUTHN_FAILED;
    }
}
Пример #2
0
Файл: shm.c Проект: ATCP/mtcp
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m,
                                         apr_size_t reqsize,
                                         const char *file,
                                         apr_pool_t *pool)
{
    static apr_size_t memblock = 0;
    HANDLE hMap, hFile;
    apr_status_t rv;
    apr_size_t size;
    apr_file_t *f;
    void *base;
    void *mapkey;
    DWORD err, sizelo, sizehi;

    reqsize += sizeof(memblock_t);

    if (!memblock)
    {
        SYSTEM_INFO si;
        GetSystemInfo(&si);
        memblock = si.dwAllocationGranularity;
    }   

    /* Compute the granualar multiple of the pagesize */
    size = memblock * (1 + (reqsize - 1) / memblock);
    sizelo = (DWORD)size;
#ifdef _WIN64
    sizehi = (DWORD)(size >> 32);
#else
    sizehi = 0;
#endif

    if (!file) {
        /* Do Anonymous, which must be passed as a duplicated handle */
#ifndef _WIN32_WCE
        hFile = INVALID_HANDLE_VALUE;
#endif
        mapkey = NULL;
    }
    else {
        /* Do file backed, which is not an inherited handle 
         * While we could open APR_EXCL, it doesn't seem that Unix
         * ever did.  Ignore that error here, but fail later when
         * we discover we aren't the creator of the file map object.
         */
        rv = apr_file_open(&f, file,
                           APR_READ | APR_WRITE | APR_BINARY | APR_CREATE,
                           APR_UREAD | APR_UWRITE, pool);
        if ((rv != APR_SUCCESS)
                || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) {
            return rv;
        }
        rv = apr_file_trunc(f, size);

        /* res_name_from_filename turns file into a pseudo-name
         * without slashes or backslashes, and prepends the \global
         * prefix on Win2K and later
         */
        mapkey = res_name_from_filename(file, 1, pool);
    }

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
    {
        hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 
                                  sizehi, sizelo, mapkey);
    }
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
    {
        hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 
                                  sizehi, sizelo, mapkey);
    }
#endif
    err = apr_get_os_error();

    if (file) {
        apr_file_close(f);
    }

    if (hMap && APR_STATUS_IS_EEXIST(err)) {
        CloseHandle(hMap);
        return APR_EEXIST;
    }
    if (!hMap) {
        return err;
    }
    
    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE,
                         0, 0, size);
    if (!base) {
        CloseHandle(hMap);
        return apr_get_os_error();
    }
    
    *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
    (*m)->pool = pool;
    (*m)->hMap = hMap;
    (*m)->memblk = base;
    (*m)->size = size;

    (*m)->usrmem = (char*)base + sizeof(memblock_t);
    (*m)->length = reqsize - sizeof(memblock_t);;
    
    (*m)->memblk->length = (*m)->length;
    (*m)->memblk->size = (*m)->size;
    (*m)->filename = file ? apr_pstrdup(pool, file) : NULL;

    apr_pool_cleanup_register((*m)->pool, *m, 
                              shm_cleanup, apr_pool_cleanup_null);
    return APR_SUCCESS;
}
Пример #3
0
    mbox_cache_get(mbox_cache_info ** mlix, const char *path, apr_pool_t *p)
{
    apr_status_t rv;
    char *temp;
    apr_datum_t key;
    apr_datum_t nv;
    int tver;
    mbox_cache_info *mli;

    OPEN_DBM(p, mli, APR_DBM_READONLY, path, temp, rv);

    if (rv != APR_SUCCESS) {
        return rv;
    }

    mli->pool = p;

    apr_pool_cleanup_register(p, (void *) mli, mli_cleanup,
                              apr_pool_cleanup_null);

    key.dptr = str_cache_version;
    key.dsize = strlen(str_cache_version) + 1;

    rv = apr_dbm_fetch(mli->db, key, &nv);

    if (rv != APR_SUCCESS) {
        apr_dbm_close(mli->db);
        return rv;
    }

    memcpy(&tver, nv.dptr, sizeof(tver));

    if (tver != MBOX_CACHE_VERSION) {
        apr_dbm_close(mli->db);
        return 1;
    }
    mli->version = tver;

    key.dptr = str_cache_mtime;
    key.dsize = strlen(str_cache_mtime) + 1;

    rv = apr_dbm_fetch(mli->db, key, &nv);

    if (rv != APR_SUCCESS) {
        apr_dbm_close(mli->db);
        return rv;
    }
    memcpy(&mli->mtime, nv.dptr, sizeof(mli->mtime));

    key.dptr = str_cache_list;
    key.dsize = strlen(str_cache_list) + 1;
    rv = apr_dbm_fetch(mli->db, key, &nv);
    if (rv != APR_SUCCESS) {
        apr_dbm_close(mli->db);
        return rv;
    }
    mli->list = apr_pstrdup(p, nv.dptr);

    key.dptr = str_cache_domain;
    key.dsize = strlen(str_cache_domain) + 1;
    rv = apr_dbm_fetch(mli->db, key, &nv);
    if (rv != APR_SUCCESS) {
        apr_dbm_close(mli->db);
        return rv;
    }
    mli->domain = apr_pstrdup(p, nv.dptr);

    *mlix = mli;

    return rv;
}
Пример #4
0
apr_status_t proc_connect_ipc(fcgid_procnode *procnode, fcgid_ipc *ipc_handle)
{
    /* Prepare the ipc struct */
    fcgid_namedpipe_handle *handle_info;

    ipc_handle->ipc_handle_info =
        (fcgid_namedpipe_handle *) apr_pcalloc(ipc_handle->request->pool,
                                               sizeof
                                               (fcgid_namedpipe_handle));
    handle_info = (fcgid_namedpipe_handle *) ipc_handle->ipc_handle_info;

    /* Prepare OVERLAPPED struct for non-block I/O */
    handle_info->overlap_read.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    handle_info->overlap_write.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    handle_info->handle_pipe = INVALID_HANDLE_VALUE;

    apr_pool_cleanup_register(ipc_handle->request->pool,
                              handle_info,
                              ipc_handle_cleanup, apr_pool_cleanup_null);

    if (handle_info->overlap_read.hEvent == NULL
            || handle_info->overlap_write.hEvent == NULL)
        return APR_ENOMEM;

    /* Connect to name pipe */
    handle_info->handle_pipe = CreateFile(procnode->socket_path,
                                          GENERIC_READ | GENERIC_WRITE,
                                          0, NULL, OPEN_EXISTING,
                                          FILE_FLAG_OVERLAPPED, NULL);

    if (handle_info->handle_pipe == INVALID_HANDLE_VALUE
        && ipc_handle->connect_timeout != 0
        && GetLastError() == ERROR_PIPE_BUSY)
    {
        /* XXX - there appears to be a race, here
         * Wait for pipe to be ready for connect, and try again
         */
        if (WaitNamedPipe(procnode->socket_path, ipc_handle->connect_timeout))
        {
            handle_info->handle_pipe = CreateFile(procnode->socket_path,
                                                  GENERIC_READ | GENERIC_WRITE,
                                                  0, NULL, OPEN_EXISTING,
                                                  FILE_FLAG_OVERLAPPED, NULL);
        }
    }

    if (handle_info->handle_pipe == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == ERROR_FILE_NOT_FOUND) /* The process has exited */
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, ipc_handle->request,
                          "mod_fcgid: can't connect to named pipe, FastCGI"
                          " server %" APR_PID_T_FMT " has been terminated",
                          procnode->proc_id.pid);
        else
            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, apr_get_os_error(),
                          ipc_handle->request,
                          "mod_fcgid: can't connect to named pipe, FastCGI"
                          " server pid %" APR_PID_T_FMT,
                          procnode->proc_id.pid);
        return APR_ESPIPE;
    }

    /* Now named pipe connected */
    return APR_SUCCESS;
}
Пример #5
0
static apr_status_t file_dup(apr_file_t **new_file, 
                             apr_file_t *old_file, apr_pool_t *p,
                             int which_dup)
{
    int rv;
#ifdef HAVE_DUP3
    int flags = 0;
#endif

    if (which_dup == 2) {
        if ((*new_file) == NULL) {
            /* We can't dup2 unless we have a valid new_file */
            return APR_EINVAL;
        }
#ifdef HAVE_DUP3
        if (!((*new_file)->flags & (APR_FILE_NOCLEANUP|APR_INHERIT)))
            flags |= O_CLOEXEC;
        rv = dup3(old_file->filedes, (*new_file)->filedes, flags);
#else
        rv = dup2(old_file->filedes, (*new_file)->filedes);
        if (!((*new_file)->flags & (APR_FILE_NOCLEANUP|APR_INHERIT))) {
            int flags;

            if (rv == -1)
                return errno;

            if ((flags = fcntl((*new_file)->filedes, F_GETFD)) == -1)
                return errno;

            flags |= FD_CLOEXEC;
            if (fcntl((*new_file)->filedes, F_SETFD, flags) == -1)
                return errno;

        }
#endif
    } else {
        rv = dup(old_file->filedes);
    }

    if (rv == -1)
        return errno;
    
    if (which_dup == 1) {
        (*new_file) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
        (*new_file)->pool = p;
        (*new_file)->filedes = rv;
    }

    (*new_file)->fname = apr_pstrdup(p, old_file->fname);
    (*new_file)->buffered = old_file->buffered;

    /* If the existing socket in a dup2 is already buffered, we
     * have an existing and valid (hopefully) mutex, so we don't
     * want to create it again as we could leak!
     */
#if APR_HAS_THREADS
    if ((*new_file)->buffered && !(*new_file)->thlock && old_file->thlock) {
        apr_thread_mutex_create(&((*new_file)->thlock),
                                APR_THREAD_MUTEX_DEFAULT, p);
    }
#endif
    /* As above, only create the buffer if we haven't already
     * got one.
     */
    if ((*new_file)->buffered && !(*new_file)->buffer) {
        (*new_file)->buffer = apr_palloc(p, old_file->bufsize);
        (*new_file)->bufsize = old_file->bufsize;
    }

    /* this is the way dup() works */
    (*new_file)->blocking = old_file->blocking; 

    /* make sure unget behavior is consistent */
    (*new_file)->ungetchar = old_file->ungetchar;

    /* apr_file_dup2() retains the original cleanup, reflecting 
     * the existing inherit and nocleanup flags.  This means, 
     * that apr_file_dup2() cannot be called against an apr_file_t
     * already closed with apr_file_close, because the expected
     * cleanup was already killed.
     */
    if (which_dup == 2) {
        return APR_SUCCESS;
    }

    /* apr_file_dup() retains all old_file flags with the exceptions
     * of APR_INHERIT and APR_FILE_NOCLEANUP.
     * The user must call apr_file_inherit_set() on the dupped 
     * apr_file_t when desired.
     */
    (*new_file)->flags = old_file->flags
                       & ~(APR_INHERIT | APR_FILE_NOCLEANUP);

    apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file),
                              apr_unix_file_cleanup, 
                              apr_unix_child_file_cleanup);
#ifndef WAITIO_USES_POLL
    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
     * initialize the pollset if needed.
     */
    (*new_file)->pollset = NULL;
#endif
    return APR_SUCCESS;
}
Пример #6
0
APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in,
                                                  apr_file_t **out,
                                                  apr_int32_t blocking,
                                                  apr_pool_t *p)
{
#ifdef _WIN32_WCE
    return APR_ENOTIMPL;
#else
    SECURITY_ATTRIBUTES sa;
    static unsigned long id = 0;
    DWORD dwPipeMode;
    DWORD dwOpenMode;
    char name[50];

    sa.nLength = sizeof(sa);
    
#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
        sa.bInheritHandle = FALSE;
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
        sa.bInheritHandle = TRUE;
#endif
    sa.lpSecurityDescriptor = NULL;

    (*in) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
    (*in)->pool = p;
    (*in)->fname = NULL;
    (*in)->pipe = 1;
    (*in)->timeout = -1;
    (*in)->ungetchar = -1;
    (*in)->eof_hit = 0;
    (*in)->filePtr = 0;
    (*in)->bufpos = 0;
    (*in)->dataRead = 0;
    (*in)->direction = 0;
    (*in)->pOverlapped = NULL;
    (void) apr_pollset_create(&(*in)->pollset, 1, p, 0);

    (*out) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t));
    (*out)->pool = p;
    (*out)->fname = NULL;
    (*out)->pipe = 1;
    (*out)->timeout = -1;
    (*out)->ungetchar = -1;
    (*out)->eof_hit = 0;
    (*out)->filePtr = 0;
    (*out)->bufpos = 0;
    (*out)->dataRead = 0;
    (*out)->direction = 0;
    (*out)->pOverlapped = NULL;
    (void) apr_pollset_create(&(*out)->pollset, 1, p, 0);

    if (apr_os_level >= APR_WIN_NT) {
        /* Create the read end of the pipe */
        dwOpenMode = PIPE_ACCESS_INBOUND;
        if (blocking == APR_WRITE_BLOCK /* READ_NONBLOCK */
               || blocking == APR_FULL_NONBLOCK) {
            dwOpenMode |= FILE_FLAG_OVERLAPPED;
            (*in)->pOverlapped = (OVERLAPPED*) apr_pcalloc(p, sizeof(OVERLAPPED));
            (*in)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            (*in)->timeout = 0;
        }

        dwPipeMode = 0;

        sprintf(name, "\\\\.\\pipe\\apr-pipe-%u.%lu", getpid(), id++);

        (*in)->filehand = CreateNamedPipe(name,
                                          dwOpenMode,
                                          dwPipeMode,
                                          1,            //nMaxInstances,
                                          0,            //nOutBufferSize, 
                                          65536,        //nInBufferSize,                   
                                          1,            //nDefaultTimeOut,                
                                          &sa);

        /* Create the write end of the pipe */
        dwOpenMode = FILE_ATTRIBUTE_NORMAL;
        if (blocking == APR_READ_BLOCK /* WRITE_NONBLOCK */
                || blocking == APR_FULL_NONBLOCK) {
            dwOpenMode |= FILE_FLAG_OVERLAPPED;
            (*out)->pOverlapped = (OVERLAPPED*) apr_pcalloc(p, sizeof(OVERLAPPED));
            (*out)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            (*out)->timeout = 0;
        }
        
        (*out)->filehand = CreateFile(name,
                                      GENERIC_WRITE,   // access mode
                                      0,               // share mode
                                      &sa,             // Security attributes
                                      OPEN_EXISTING,   // dwCreationDisposition
                                      dwOpenMode,      // Pipe attributes
                                      NULL);           // handle to template file
    }
    else {
        /* Pipes on Win9* are blocking. Live with it. */
        if (!CreatePipe(&(*in)->filehand, &(*out)->filehand, &sa, 65536)) {
            return apr_get_os_error();
        }
    }

    apr_pool_cleanup_register((*in)->pool, (void *)(*in), file_cleanup,
                        apr_pool_cleanup_null);
    apr_pool_cleanup_register((*out)->pool, (void *)(*out), file_cleanup,
                        apr_pool_cleanup_null);
    return APR_SUCCESS;
#endif /* _WIN32_WCE */
}
Пример #7
0
/**
 * @brief Create a context for supporting encryption. Keys, certificates,
 *        algorithms and other parameters will be set per context. More than
 *        one context can be created at one time. A cleanup will be automatically
 *        registered with the given pool to guarantee a graceful shutdown.
 * @param f - context pointer will be written here
 * @param provider - provider to use
 * @param params - array of key parameters
 * @param pool - process pool
 * @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
 * if the engine cannot be initialised.
 */
static apr_status_t crypto_make(apr_crypto_t **ff,
        const apr_crypto_driver_t *provider, const char *params,
        apr_pool_t *pool)
{
    apr_crypto_config_t *config = NULL;
    apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t));

    const char *engine = NULL;

    struct {
        const char *field;
        const char *value;
        int set;
    } fields[] = {
        { "engine", NULL, 0 },
        { NULL, NULL, 0 }
    };
    const char *ptr;
    size_t klen;
    char **elts = NULL;
    char *elt;
    int i = 0, j;
    apr_status_t status;

    if (params) {
        if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) {
            return status;
        }
        while ((elt = elts[i])) {
            ptr = strchr(elt, '=');
            if (ptr) {
                for (klen = ptr - elt; klen && apr_isspace(elt[klen - 1]); --klen)
                    ;
                ptr++;
            }
            else {
                for (klen = strlen(elt); klen && apr_isspace(elt[klen - 1]); --klen)
                    ;
            }
            elt[klen] = 0;

            for (j = 0; fields[j].field != NULL; ++j) {
                if (!strcasecmp(fields[j].field, elt)) {
                    fields[j].set = 1;
                    if (ptr) {
                        fields[j].value = ptr;
                    }
                    break;
                }
            }

            i++;
        }
        engine = fields[0].value;
    }

    if (!f) {
        return APR_ENOMEM;
    }
    *ff = f;
    f->pool = pool;
    f->provider = provider;
    config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t));
    if (!config) {
        return APR_ENOMEM;
    }

    f->result = apr_pcalloc(pool, sizeof(apu_err_t));
    if (!f->result) {
        return APR_ENOMEM;
    }

    f->keys = apr_array_make(pool, 10, sizeof(apr_crypto_key_t));
    if (!f->keys) {
        return APR_ENOMEM;
    }

    f->types = apr_hash_make(pool);
    if (!f->types) {
        return APR_ENOMEM;
    }
    apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_3des_192));
    apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_aes_128));
    apr_hash_set(f->types, "aes192", APR_HASH_KEY_STRING, &(key_aes_192));
    apr_hash_set(f->types, "aes256", APR_HASH_KEY_STRING, &(key_aes_256));

    f->modes = apr_hash_make(pool);
    if (!f->modes) {
        return APR_ENOMEM;
    }
    apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(mode_ecb));
    apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(mode_cbc));

    apr_pool_cleanup_register(pool, f, crypto_cleanup_helper,
            apr_pool_cleanup_null);

    if (engine) {
        config->engine = ENGINE_by_id(engine);
        if (!config->engine) {
            return APR_ENOENGINE;
        }
        if (!ENGINE_init(config->engine)) {
            ENGINE_free(config->engine);
            config->engine = NULL;
            return APR_EINITENGINE;
        }
    }

    return APR_SUCCESS;

}
Пример #8
0
/* FIXME: This is a rather nasty possible failure point.  I have no
   idea how to test this. */
int kdkey_extract_tm_pkey(apr_pool_t *pool,
                          const char *str_key, 
                          size_t str_key_s, 
                          struct kdkey_info *ki) {
    int error = -1;
    struct kdsh_tm_pkey_time tm_pkey_time[2];
    struct tagcrypt_signed_pkey *tm_pkey_obj[2] = {NULL, NULL};
    struct tagcrypt_signed_pkey *signed_pkey;
    kbuffer *buf = kbuffer_new();
    int cur_key, old_key;
    
    /* TRY */
    do {
        kbuffer_write(buf, (uint8_t *)str_key, str_key_s);
        signed_pkey = tagcrypt_sign_get_pkey(buf, master_pkey_info.key);

        if (!signed_pkey) {
            KERROR_SET(_shared_, 0, "error getting the signed public timestamp key");
            break;
        }

        kdsh_lock();
        cur_key = kdsh_get_cur_tm_pkey();
        old_key = !cur_key;

        kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]);
        kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]);

        /* This is the first tm key we receive */
        if (tm_pkey_time[cur_key].status == 0) {
            if (kdsh_set_cur_tm_pkey_time(signed_pkey)) {
                KERROR_PUSH(_shared_, 0, "error saving new timestamp key");
                break;
            }
            kdsh_set_cur_tm_pkey_time(signed_pkey);
        }

        /* We are receiving the current key (Normal path) */
        else if (tm_pkey_time[cur_key].activation_time.tv_sec == signed_pkey->time.tv_sec) {
            struct timeval tv;
            /* Is there an old key ? */
            if (tm_pkey_time[old_key].status == 1) {
                if (gettimeofday(&tv, NULL) == -1) {
                    KERROR_SET(_shared_, 0, "could not gettimeofday: %s", strerror(errno));
                    break;
                }
                /* Flush it if it's too old */
                if (tm_pkey_time[cur_key].received_time.tv_sec + KSH_KEY_TIMEOUT < tv.tv_sec) {
                    tm_pkey_time[old_key].status = 0;
                    tagcrypt_signed_pkey_destroy(tm_pkey_obj[old_key]);
                }
            }

            /* Check if an instance of the current_key is available */
            if (tm_pkey_obj[cur_key] == NULL) { /* not in cache for this process */
                tm_pkey_obj[cur_key] = signed_pkey;
            } else {
                tagcrypt_signed_pkey_destroy(signed_pkey);
                signed_pkey = tm_pkey_obj[cur_key];
            }
        }

        /* We are receiving a new key for the first time */
        else if (tm_pkey_time[old_key].status == 0) {

            /* This new key is older than the current one */
            if (tm_pkey_time[cur_key].activation_time.tv_sec > signed_pkey->time.tv_sec) {
                KERROR_SET(_shared_, 0, "received an outdated timestamp key");
                break;
            }

            kdsh_switch_tm_pkey_time();
            cur_key = kdsh_get_cur_tm_pkey();
            old_key = !cur_key;

            kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]);
            kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]);

            if (kdsh_set_cur_tm_pkey_time(signed_pkey) < 0) {
                kdsh_switch_tm_pkey_time();
                KERROR_PUSH(_shared_, 0, "error saving new timestamp key");
                break;
            }
            tm_pkey_obj[cur_key] = signed_pkey;
        }

        /* We are receiving an old key, let's see if it's still valid. */
        else if (tm_pkey_time[old_key].activation_time.tv_sec == signed_pkey->time.tv_sec) {
            /* Check if an instance of the current_key is available */
            if (tm_pkey_obj[old_key] == NULL) { /* not in cache for this process */
                tm_pkey_obj[old_key] = signed_pkey;
            } else {
                tagcrypt_signed_pkey_destroy(signed_pkey);
                signed_pkey = tm_pkey_obj[old_key];
            }
        }
        /* This is an unknown old key */
        else 
            KERROR_SET(_shared_, 0, "received an outdated timestamp key");
	
	error = 0;

    } while (0);

    if (error) {
        tagcrypt_signed_pkey_destroy(signed_pkey);
        signed_pkey = NULL;
    } 
    else {
        ki->owner = KEY_OWNER;
        ki->owner_s = KEY_OWNER_S;
        ki->data = NULL;
        ki->data_s = 0;
        ki->key = signed_pkey->key;
        /* HACK: We should not free structures under the nose of
           tagcryp.t */
        kfree(signed_pkey);

        apr_pool_cleanup_register(pool, ki->key,
                                  kdkey_destroy_pkey, kdkey_destroy_pkey);
    }

    kdsh_unlock();
    kbuffer_destroy(buf);

    return error;
}
Пример #9
0
/* 
 * Passing NULL as the timestamp_pkey is a dirty hack to bypass
 * the signature verification. 
 *
 * This function does not, in fact, allocate anything on the pool, but
 * uses it to destroy the key.
 */
int kdkey_extract_signed_pkey(apr_pool_t *pool,
                              struct kdkey_info *tm_pkey,
                              const char *str_key,
                              size_t str_key_s,
                              struct kdkey_info *ki) {
    int error = -1;
    kbuffer *pkey_buffer;
    struct kdsh_tm_pkey_time tm_pkey_time[2];
    struct tagcrypt_signed_pkey *signed_pkey = NULL;
    int cur_key, old_key;
    struct timeval tm;
    tagcrypt_pkey *key;

    pkey_buffer = kbuffer_new();

    /* No locking is needed as we only want to store an approximate
       time. If there's a race, we'll still have an approximation of
       the time anyway. */

    do {
        cur_key = kdsh_get_cur_tm_pkey();
        old_key = !cur_key;

        kdsh_get_cur_tm_pkey_time(&tm_pkey_time[cur_key]);
        kdsh_get_old_tm_pkey_time(&tm_pkey_time[old_key]);

        kbuffer_write(pkey_buffer, (uint8_t *)str_key, str_key_s);
      
        if (tm_pkey == NULL) key = NULL; else key = tm_pkey->key;                                 
        if ((signed_pkey = tagcrypt_sign_get_pkey(pkey_buffer, key)) == NULL) {
            KERROR_SET(_keys_, 0, "cannot create public key from signed key");
            break;
        }

        if (tm_pkey == NULL && signed_pkey->mid != 0) {
            KERROR_SET(_keys_, 0, "invalid timestamp key for the signature");
            tagcrypt_signed_pkey_destroy(signed_pkey);
            break;
        }

        kdsh_get_timestamp(&tm);

        if (tm.tv_sec == 0 || tm.tv_sec - KSH_KEY_TIMEOUT <= signed_pkey->time.tv_sec) {
            if (tm_pkey != NULL) 
                tm.tv_sec = signed_pkey->time.tv_sec;
            
            ki->owner = KEY_OWNER;
            ki->owner_s = KEY_OWNER_S;
            ki->data = NULL;
            ki->data_s = 0;
            ki->key = signed_pkey->key;

            /* HACK: We should not free structure memory under the
               nose of tagcrypt that way. */
            kfree(signed_pkey);

            apr_pool_cleanup_register(pool, ki->key, 
                                      kdkey_destroy_pkey, kdkey_destroy_pkey);
        } 
        else {
            KERROR_SET(_keys_, 0, "received an outdated public key");
            tagcrypt_signed_pkey_destroy(signed_pkey);
        }
	
	error = 0;
    } while (0);

    if (error) {
        tagcrypt_signed_pkey_destroy(signed_pkey);
        signed_pkey = NULL;
    }

    kbuffer_destroy(pkey_buffer);

    return error;
}
Пример #10
0
apr_status_t
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
                            const char *service,
                            const char *hostname,
                            serf__kerb_buffer_t *input_buf,
                            serf__kerb_buffer_t *output_buf,
                            apr_pool_t *scratch_pool,
                            apr_pool_t *result_pool
                            )
{
    SECURITY_STATUS status;
    ULONG actual_attr;
    SecBuffer sspi_in_buffer;
    SecBufferDesc sspi_in_buffer_desc;
    SecBuffer sspi_out_buffer;
    SecBufferDesc sspi_out_buffer_desc;
    char *target_name;
    apr_status_t apr_status;
    const char *canonname;

    apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool);
    if (apr_status) {
        return apr_status;
    }
    target_name = apr_pstrcat(scratch_pool, service, "/", canonname, NULL);

    /* Prepare input buffer description. */
    sspi_in_buffer.BufferType = SECBUFFER_TOKEN;
    sspi_in_buffer.pvBuffer = input_buf->value;
    sspi_in_buffer.cbBuffer = input_buf->length; 

    sspi_in_buffer_desc.cBuffers = 1;
    sspi_in_buffer_desc.pBuffers = &sspi_in_buffer;
    sspi_in_buffer_desc.ulVersion = SECBUFFER_VERSION;

    /* Output buffers. Output buffer will be allocated by system. */
    sspi_out_buffer.BufferType = SECBUFFER_TOKEN;
    sspi_out_buffer.pvBuffer = NULL; 
    sspi_out_buffer.cbBuffer = 0;

    sspi_out_buffer_desc.cBuffers = 1;
    sspi_out_buffer_desc.pBuffers = &sspi_out_buffer;
    sspi_out_buffer_desc.ulVersion = SECBUFFER_VERSION;

    status = InitializeSecurityContext(
        &ctx->sspi_credentials,
        ctx->initalized ? &ctx->sspi_context : NULL,
        target_name,
        ISC_REQ_ALLOCATE_MEMORY
        | ISC_REQ_MUTUAL_AUTH
        | ISC_REQ_CONFIDENTIALITY,
        0,                          /* Reserved1 */
        SECURITY_NETWORK_DREP,
        &sspi_in_buffer_desc,
        0,                          /* Reserved2 */
        &ctx->sspi_context,
        &sspi_out_buffer_desc,
        &actual_attr,
        NULL);

    if (sspi_out_buffer.cbBuffer > 0) {
        apr_pool_cleanup_register(result_pool, sspi_out_buffer.pvBuffer,
                                  cleanup_sec_buffer,
                                  apr_pool_cleanup_null);
    }

    ctx->initalized = TRUE;

    /* Finish authentication if SSPI requires so. */
    if (status == SEC_I_COMPLETE_NEEDED
        || status == SEC_I_COMPLETE_AND_CONTINUE)
    {
        CompleteAuthToken(&ctx->sspi_context, &sspi_out_buffer_desc);
    }

    output_buf->value = sspi_out_buffer.pvBuffer;
    output_buf->length = sspi_out_buffer.cbBuffer;

    switch(status) {
    case SEC_I_COMPLETE_AND_CONTINUE:
    case SEC_I_CONTINUE_NEEDED:
        return APR_EAGAIN;

    case SEC_I_COMPLETE_NEEDED:
    case SEC_E_OK:
        return APR_SUCCESS;

    default:
        return APR_EGENERAL;
    }
}
Пример #11
0
/** Return an ordinary key object.  Returns -1 on error, 0 on missing
    key, and 1 on success. */
int kdkey_get_key(apr_pool_t *pool, 
                  uint64_t key_id, 
                  enum kdkey_type ktype, 
                  struct kdkey_info **ki) {
    kbuffer buf;
    enum key_type type;
    kstr str;
    int err = 0;
    
    assert((ktype > SKEY_START && ktype < SKEY_END) ||
           (ktype > PKEY_START && ktype < PKEY_END));

    switch (ktype) {
        /* Those go through the database object. */
    case SKEY_ENCRYPTION:
    case SKEY_SIGNATURE:
    case PKEY_ENCRYPTION:
    case PKEY_SIGNATURE:
        err = kddb_fetch_key(pool, key_id, ktype, ki);
        /* Key fetch error. */
        if (err < 0) {
            KERROR_PUSH(_keys_, 0, "failed to fetch key "PRINTF_64"u", key_id);
            err = -1;
            break;
        }
        /* Key not found. */
        if (err == 0) return 0;

        type = kdkey_to_tagcrypt(ktype);
        kstr_init_buf(&str, (*ki)->data, (*ki)->data_s);
        err = kbuffer_init_b64(&buf, &str);
        kstr_clean(&str);

        if (err) break;

        if (ktype == SKEY_ENCRYPTION || ktype == SKEY_SIGNATURE) {
            (*ki)->key = tagcrypt_skey_new(&buf);        

            if ((*ki)->key == NULL) {
                KERROR_SET(_keys_, 0, "ill-formed secret key in database");
                err = -1;
                break;
            }

            /* Check for inconsistent key ID. */
            if (((tagcrypt_skey *)(*ki)->key)->keyid != (*ki)->key_id) {
                KERROR_SET(_keys_, 0, 
                           "ill-formed key, internal key ID: "PRINTF_64"u, external key ID: "PRINTF_64"u", 
                           ((tagcrypt_skey *)(*ki)->key)->keyid, (*ki)->key_id);
                err = -1;
                break;
            }

            /* Register memory cleanup function. */
            if ((*ki)->key != NULL)
                apr_pool_cleanup_register(pool, (*ki)->key, kdkey_destroy_skey, kdkey_destroy_skey);
        } 
        else if (ktype == PKEY_ENCRYPTION || ktype == PKEY_SIGNATURE) {
            (*ki)->key = tagcrypt_pkey_new(&buf, type);        

            if ((*ki)->key == NULL) {
                KERROR_SET(_keys_, 0, "ill-formed public key in database");
                err = -1;
                break;
            }

            /* Check for inconsistent key ID. */
            if (((tagcrypt_pkey *)(*ki)->key)->keyid != (*ki)->key_id) {
                KERROR_SET(_keys_, 0, 
                           "ill-formed key, internal key ID: "PRINTF_64"u, external key ID: "PRINTF_64"u", 
                           ((tagcrypt_pkey *)(*ki)->key)->keyid, (*ki)->key_id);
                err = -1;
                break;
            }
            
            /* Register memory cleanup function. */
            if ((*ki)->key != NULL)
                apr_pool_cleanup_register(pool, (*ki)->key, kdkey_destroy_pkey, kdkey_destroy_pkey);
        }

        if ((*ki)->key == NULL) {
            err = -1;
            KERROR_SET(_keys_, 0, "failed to create key "PRINTF_64"u", key_id);
        }

        kbuffer_clean(&buf);
        err = 1;
        break;

    case PKEY_TIMESTAMP:
        *ki = &tm_pkey_info;
        break;

    case PKEY_LICENSE:
        *ki = &license_pkey_info;
        break;

#ifdef REQUEST_GETSIG
    case SKEY_TIMESTAMP:
        *ki = &tm_skey_info;
        break;

#endif // REQUEST_GETSIG

    default:
        abort();
    }
    
    return err;
}
Пример #12
0
svn_error_t *
svn_atomic_namespace__create(svn_atomic_namespace__t **ns,
                             const char *name,
                             apr_pool_t *result_pool)
{
  apr_status_t apr_err;
  svn_error_t *err;
  apr_file_t *file;
  apr_mmap_t *mmap;
  const char *shm_name, *lock_name;
  apr_finfo_t finfo;

  apr_pool_t *subpool = svn_pool_create(result_pool);

  /* allocate the namespace data structure
   */
  svn_atomic_namespace__t *new_ns = apr_pcalloc(result_pool, sizeof(**ns));

  /* construct the names of the system objects that we need
   */
  shm_name = apr_pstrcat(subpool, name, SHM_NAME_SUFFIX, NULL);
  lock_name = apr_pstrcat(subpool, name, MUTEX_NAME_SUFFIX, NULL);

  /* initialize the lock objects
   */
  SVN_ERR(svn_atomic__init_once(&mutex_initialized, init_thread_mutex, NULL,
                                result_pool));

  new_ns->mutex.pool = result_pool;
  SVN_ERR(svn_io_file_open(&new_ns->mutex.lock_file, lock_name,
                           APR_READ | APR_WRITE | APR_CREATE,
                           APR_OS_DEFAULT,
                           result_pool));

  /* Make sure the last user of our lock file will actually remove it.
   * Please note that only the last file handle begin closed will actually
   * remove the underlying file (see docstring for apr_file_remove).
   */
  apr_pool_cleanup_register(result_pool, &new_ns->mutex,
                            delete_lock_file,
                            apr_pool_cleanup_null);

  /* Prevent concurrent initialization.
   */
  SVN_ERR(lock(&new_ns->mutex));

  /* First, make sure that the underlying file exists.  If it doesn't
   * exist, create one and initialize its content.
   */
  err = svn_io_file_open(&file, shm_name,
                          APR_READ | APR_WRITE | APR_CREATE,
                          APR_OS_DEFAULT,
                          result_pool);
  if (!err)
    {
      err = svn_io_stat(&finfo, shm_name, APR_FINFO_SIZE, subpool);
      if (!err && finfo.size < sizeof(struct shared_data_t))
        {
           /* Zero all counters, values and names.
            */
           struct shared_data_t initial_data;
           memset(&initial_data, 0, sizeof(initial_data));
           err = svn_io_file_write_full(file, &initial_data,
                                        sizeof(initial_data), NULL,
                                        subpool);
        }
    }

  /* Now, map it into memory.
   */
  if (!err)
    {
      apr_err = apr_mmap_create(&mmap, file, 0, sizeof(*new_ns->data),
                                APR_MMAP_READ | APR_MMAP_WRITE , result_pool);
      if (!apr_err)
        new_ns->data = mmap->mm;
      else
        err = svn_error_createf(apr_err, NULL,
                                _("MMAP failed for file '%s'"), shm_name);
    }

  svn_pool_destroy(subpool);

  if (!err && new_ns->data)
    {
      /* Detect severe cases of corruption (i.e. when some outsider messed
       * with our data file)
       */
      if (new_ns->data->count > MAX_ATOMIC_COUNT)
        return svn_error_create(SVN_ERR_CORRUPTED_ATOMIC_STORAGE, 0,
                       _("Number of atomics in namespace is too large."));

      /* Cache the number of existing, complete entries.  There can't be
       * incomplete ones from other processes because we hold the mutex.
       * Our process will also not access this information since we are
       * either being called from within svn_atomic__init_once or by
       * svn_atomic_namespace__create for a new object.
       */
      new_ns->min_used = new_ns->data->count;
      *ns = new_ns;
    }

  /* Unlock to allow other processes may access the shared memory as well.
   */
  return unlock(&new_ns->mutex, err);
}
Пример #13
0
static int perl_metric_init(apr_pool_t *p)
{
    DIR *dp;
    struct dirent *entry;
    int i, size;
    char* modname;
    char *modpath;
    HV *pparamhash;
    pl_metric_init_t minfo;
    Ganglia_25metric *gmi;
    mapped_info_t *mi;
    const char* path = perl_module.module_params;
    cfg_t *module_cfg;
    PerlInterpreter *perl = NULL;
    int argc = 0;
	char *argv[] = { };
	char *env[] = { };
	char *embedding[] = {"", ""};

    /* Allocate a pool that will be used by this module */
    apr_pool_create(&pool, p);

    metric_info = apr_array_make(pool, 10, sizeof(Ganglia_25metric));
    metric_mapping_info = apr_array_make(pool, 10, sizeof(mapped_info_t));

    /* Verify path exists and can be read */

    if (!path) {
        err_msg("[PERL] Missing perl module path.\n");
        return -1;
    }

    if (access(path, F_OK)) {
        /* 'path' does not exist */
        err_msg("[PERL] Can't open the perl module path %s.\n", path);
        return -1;
    }

    if (access(path, R_OK)) {
        /* Don't have read access to 'path' */
        err_msg("[PERL] Can't read from the perl module path %s.\n", path);
        return -1;
    }

    /* Initialize each perl module */
    if ((dp = opendir(path)) == NULL) {
        /* Error: Cannot open the directory - Shouldn't happen */
        /* Log? */
        err_msg("[PERL] Can't open the perl module path %s.\n", path);
        return -1;
    }

    PERL_SYS_INIT3(&argc, (char ***) &argv, (char ***) &env);

    i = 0;

    while ((entry = readdir(dp)) != NULL) {
        modname = is_perl_module(entry->d_name);
        if (modname == NULL)
            continue;

        /* Find the specified module configuration in gmond.conf 
           If this return NULL then either the module config
           doesn't exist or the module is disabled. */
        module_cfg = find_module_config(modname);
        if (!module_cfg)
            continue;

        size_t path_len = strlen(path) + strlen(modname) + 5;
        modpath = malloc(path_len);
        modpath = strncpy(modpath, path, path_len);
        modpath = strcat(modpath, "/");
        modpath = strcat(modpath, modname);
        modpath = strcat(modpath, ".pl");

        embedding[1] = modpath ;

        perl = perl_alloc();
        PL_perl_destruct_level = 0;

        PERL_SET_CONTEXT(perl);
        perl_construct(perl);
        PL_origalen = 1;

        PERL_SET_CONTEXT(perl);
        perl_parse(perl, NULL, 1, embedding, NULL);

        /* Run the perl script so that global variables can be accessed */
        perl_run(perl);

        free(modpath);

        /* Build a parameter dictionary to pass to the module */
        pparamhash = build_params_hash(module_cfg);
        if (!pparamhash) {
            err_msg("[PERL] Can't build the parameters hash for [%s].\n", modname);
            continue;
        }

        dSP;
        ENTER;
        SAVETMPS;
        PUSHMARK(SP);
        /* Push a reference to the pparamhash to the Perl stack */
        XPUSHs(sv_2mortal(newRV_noinc((SV*)pparamhash)));
        PUTBACK;
        size = call_pv("metric_init", G_ARRAY|G_EVAL);
        SPAGAIN;
        /*SP -= size;
        ax = (SP - PL_stack_base) + 1;
        SvGETMAGIC(plarray); */

        if (SvTRUE(ERRSV)) {
            /* failed calling metric_init */
            err_msg("[PERL] Can't call the metric_init function in the perl module [%s].\n", modname);
            continue;
        }
        else {
            if (size) {
                int j;
                for (j = 0; j < size; j++) {
                    SV* sref = POPs;
                    if (!SvROK(sref)) {
                        err_msg("[PERL] No descriptors returned from metric_init call in the perl module [%s].\n", modname);
                        continue;
                    }

                    /* Dereference the reference */
                    HV* plhash = (HV*)(SvRV(sref));
                    if (plhash != NULL) {
                        fill_metric_info(plhash, &minfo, modname, pool);
                        gmi = (Ganglia_25metric*)apr_array_push(metric_info);
                        fill_gmi(gmi, &minfo);
                        mi = (mapped_info_t*)apr_array_push(metric_mapping_info);
                        mi->mod_name = apr_pstrdup(pool, modname);
                        mi->pcb = apr_pstrdup(pool, minfo.pcb);
                        mi->perl = perl;
                    }
                }
            }
        }

        PUTBACK;
        FREETMPS;
        LEAVE;

    }
    closedir(dp);

    apr_pool_cleanup_register(pool, NULL,
                              perl_metric_cleanup,
                              apr_pool_cleanup_null);

    /* Replace the empty static metric definition array with the
       dynamic array that we just created 
     */
    /*XXX Need to put this into a finalize MACRO. This is just pushing
      a NULL entry onto the array so that the looping logic can 
      determine the end if the array. We should probably give back
      a ready APR array rather than a pointer to a Ganglia_25metric
      array. */
    gmi = apr_array_push(metric_info);
    memset (gmi, 0, sizeof(*gmi));
    mi = apr_array_push(metric_mapping_info);
    memset (mi, 0, sizeof(*mi));

    perl_module.metrics_info = (Ganglia_25metric *)metric_info->elts;
    return 0;
}
Пример #14
0
/* run in post_read_request hook */
static int ruid_setup (request_rec *r)
{
	/* We decline when we are in a subrequest. The ruid_setup function was
	 * already executed in the main request. */
	if (!ap_is_initial_req(r)) {
		return DECLINED;
	}

	ruid_config_t *conf = ap_get_module_config (r->server->module_config,  &ruid2_module);
	ruid_dir_config_t *dconf = ap_get_module_config(r->per_dir_config, &ruid2_module);
	core_server_config *core = (core_server_config *) ap_get_module_config(r->server->module_config, &core_module);

	int ncap=0;
	cap_t cap;
	cap_value_t capval[2];

	if (dconf->ruid_mode==RUID_MODE_STAT) capval[ncap++] = CAP_DAC_READ_SEARCH;
	if (root_handle != UNSET) capval[ncap++] = CAP_SYS_CHROOT;
	if (ncap) {
		cap=cap_get_proc();
		cap_set_flag(cap, CAP_EFFECTIVE, ncap, capval, CAP_SET);
		if (cap_set_proc(cap)!=0) {
			ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed", MODULE_NAME, __func__);
		}
		cap_free(cap);
	}

	/* do chroot trick only if chrootdir is defined */
	if (conf->chroot_dir)
	{
		old_root = ap_document_root(r);
		core->ap_document_root = conf->document_root;
		if (chdir(conf->chroot_dir) != 0)
		{
			ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"%s %s %s chdir to %s failed", MODULE_NAME, ap_get_server_name (r), r->the_request, conf->chroot_dir);
			return HTTP_FORBIDDEN;
		}
		if (chroot(conf->chroot_dir) != 0)
		{
			ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL,"%s %s %s chroot to %s failed", MODULE_NAME, ap_get_server_name (r), r->the_request, conf->chroot_dir);
			return HTTP_FORBIDDEN;
		}

		cap = cap_get_proc();
		capval[0] = CAP_SYS_CHROOT;
		cap_set_flag(cap, CAP_EFFECTIVE, 1, capval, CAP_CLEAR);
		if (cap_set_proc(cap) != 0 )
		{
			ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s CRITICAL ERROR %s:cap_set_proc failed", MODULE_NAME, __func__);
		}
		cap_free(cap);
	}

	/* register suidback function */
	apr_pool_cleanup_register(r->pool, r, ruid_suidback, apr_pool_cleanup_null);

	if (dconf->ruid_mode==RUID_MODE_CONF)
	{
		return ruid_set_perm(r, __func__);
	} else {
		return DECLINED;
	}
}
Пример #15
0
static int pyth_metric_init (apr_pool_t *p)
{
    DIR *dp;
    struct dirent *entry;
    int i;
    char* modname;
    PyObject *pmod, *pinitfunc, *pobj, *pparamdict;
    py_metric_init_t minfo;
    Ganglia_25metric *gmi;
    mapped_info_t *mi;
    const char* path = python_module.module_params;
    cfg_t *module_cfg;

    /* Allocate a pool that will be used by this module */
    apr_pool_create(&pool, p);

    metric_info = apr_array_make(pool, 10, sizeof(Ganglia_25metric));
    metric_mapping_info = apr_array_make(pool, 10, sizeof(mapped_info_t));

    /* Verify path exists and can be read */

    if (!path) {
        err_msg("[PYTHON] Missing python module path.\n");
        return -1;
    }

    if (access(path, F_OK))
    {
        /* 'path' does not exist */
        err_msg("[PYTHON] Can't open the python module path %s.\n", path);
        return -1;
    }

    if (access(path, R_OK))
    {
        /* Don't have read access to 'path' */
        err_msg("[PYTHON] Can't read from the python module path %s.\n", path);
        return -1;
    }

    /* Init Python environment */

    /* Set up the python path to be able to load module from our module path */
    Py_Initialize();
    Py_InitModule("ganglia", GangliaMethods);

    PyObject *sys_path = PySys_GetObject("path");
    PyObject *addpath = PyString_FromString(path);
    PyList_Append(sys_path, addpath);

    PyEval_InitThreads();
    gtstate = PyEval_SaveThread();

    /* Initialize each python module */
    if ((dp = opendir(path)) == NULL) {
        /* Error: Cannot open the directory - Shouldn't happen */
        /* Log? */
        err_msg("[PYTHON] Can't open the python module path %s.\n", path);
        return -1;
    }

    i = 0;

    while ((entry = readdir(dp)) != NULL) {
        modname = is_python_module(entry->d_name);

        if (modname == NULL)
            continue;

        /* Find the specified module configuration in gmond.conf 
           If this return NULL then either the module config
           doesn't exist or the module is disabled. */
        module_cfg = find_module_config(modname);
        if (!module_cfg)
            continue;

        PyEval_RestoreThread(gtstate);

        pmod = PyImport_ImportModule(modname);
        if (!pmod) {
            /* Failed to import module. Log? */
            err_msg("[PYTHON] Can't import the metric module [%s].\n", modname);
            if (PyErr_Occurred()) {
                PyErr_Print();
            }
            gtstate = PyEval_SaveThread();
            continue;
        }

        pinitfunc = PyObject_GetAttrString(pmod, "metric_init");
        if (!pinitfunc || !PyCallable_Check(pinitfunc)) {
            /* No metric_init function. */
            err_msg("[PYTHON] Can't find the metric_init function in the python module [%s].\n", modname);
            Py_DECREF(pmod);
            gtstate = PyEval_SaveThread();
            continue;
        }

        /* Build a parameter dictionary to pass to the module */
        pparamdict = build_params_dict(module_cfg);
        if (!pparamdict || !PyDict_Check(pparamdict)) {
            /* No metric_init function. */
            err_msg("[PYTHON] Can't build the parameters dictionary for [%s].\n", modname);
            Py_DECREF(pmod);
            gtstate = PyEval_SaveThread();
            continue;
        }

        /* Now call the metric_init method of the python module */
        pobj = PyObject_CallFunction(pinitfunc, "(N)", pparamdict);

        if (!pobj) {
            /* failed calling metric_init */
            err_msg("[PYTHON] Can't call the metric_init function in the python module [%s].\n", modname);
            if (PyErr_Occurred()) {
                PyErr_Print();
            }
            Py_DECREF(pinitfunc);
            Py_DECREF(pmod);
            gtstate = PyEval_SaveThread();
            continue;
        }

        if (PyList_Check(pobj)) {
            int j;
            int size = PyList_Size(pobj);
            for (j = 0; j < size; j++) {
                PyObject* plobj = PyList_GetItem(pobj, j);
                if (PyMapping_Check(plobj)) {
                    fill_metric_info(plobj, &minfo, modname, pool);
                    gmi = (Ganglia_25metric*)apr_array_push(metric_info);
                    fill_gmi(gmi, &minfo);
                    mi = (mapped_info_t*)apr_array_push(metric_mapping_info);
                    mi->pmod = pmod;
                    mi->mod_name = apr_pstrdup(pool, modname);
                    mi->pcb = minfo.pcb;
                }
            }
        }
        else if (PyMapping_Check(pobj)) {
            fill_metric_info(pobj, &minfo, modname, pool);
            gmi = (Ganglia_25metric*)apr_array_push(metric_info);
            fill_gmi(gmi, &minfo);
            mi = (mapped_info_t*)apr_array_push(metric_mapping_info);
            mi->pmod = pmod;
            mi->mod_name = apr_pstrdup(pool, modname);
            mi->pcb = minfo.pcb;
        }
        Py_DECREF(pobj);
        Py_DECREF(pinitfunc);
        gtstate = PyEval_SaveThread();
    }
    closedir(dp);

    apr_pool_cleanup_register(pool, NULL,
                              pyth_metric_cleanup,
                              apr_pool_cleanup_null);

    /* Replace the empty static metric definition array with the
       dynamic array that we just created 
    */
    /*XXX Need to put this into a finalize MACRO. This is just pushing
      a NULL entry onto the array so that the looping logic can 
      determine the end if the array. We should probably give back
      a ready APR array rather than a pointer to a Ganglia_25metric
      array. */
    gmi = apr_array_push(metric_info);
    memset (gmi, 0, sizeof(*gmi));
    mi = apr_array_push(metric_mapping_info);
    memset (mi, 0, sizeof(*mi));

    python_module.metrics_info = (Ganglia_25metric *)metric_info->elts;
    return 0;
}
Пример #16
0
apr_status_t
procmgr_post_config(server_rec * main_server, apr_pool_t * pconf)
{
    apr_status_t rv;
    fcgid_server_conf *sconf = ap_get_module_config(main_server->module_config,
                                                    &fcgid_module);

    /* Initialize spawn controler */
    spawn_control_init(main_server, pconf);

    /* Create a message queues */
    if ((rv = apr_queue_create(&g_msgqueue, FCGID_MSGQUEUE_SIZE,
                               pconf)) != APR_SUCCESS
        || (rv = apr_queue_create(&g_notifyqueue, FCGID_MSGQUEUE_SIZE,
                                  pconf)) != APR_SUCCESS) {
        /* Fatal error */
        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, main_server,
                     "mod_fcgid: can't create message queue");
        exit(1);
    }

    /* Create request lock */
    if ((rv = apr_thread_mutex_create(&g_reqlock,
                                      APR_THREAD_MUTEX_DEFAULT,
                                      pconf)) != APR_SUCCESS) {
        /* Fatal error */
        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, main_server,
                     "mod_fcgid: Can't create request mutex");
        exit(1);
    }

    /* Calculate procmgr_fetch_cmd wake up interval */
    g_wakeup_timeout = min(sconf->error_scan_interval,
                           sconf->busy_scan_interval);
    g_wakeup_timeout = min(sconf->idle_scan_interval,
                           g_wakeup_timeout);
    if (g_wakeup_timeout == 0)
        g_wakeup_timeout = 1;   /* Make it reasonable */

    /* Create process manager worker thread */
    if ((rv = apr_thread_create(&g_thread, NULL, worker_thread,
                                main_server, pconf)) != APR_SUCCESS) {
        /* It's a fatal error */
        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, main_server,
                     "mod_fcgid: can't create process manager thread");
        exit(1);
    }

    /* Create wake up thread */
    /* XXX If there was a function such like apr_queue_pop_timedwait(),
       then I don't need such an ugly thread to do the wake up job */
    if ((rv = apr_thread_create(&g_wakeup_thread, NULL, wakeup_thread,
                                NULL, pconf)) != APR_SUCCESS) {
        /* It's a fatal error */
        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, main_server,
                     "mod_fcgid: can't create wake up thread");
        exit(1);
    }

    apr_pool_cleanup_register(pconf, main_server, procmgr_stop_procmgr,
                              apr_pool_cleanup_null);

    return APR_SUCCESS;
}
Пример #17
0
bool InitAPRGlobalStorage (APRGlobalStorage *storage_p, apr_pool_t *pool_p, apr_hashfunc_t hash_fn, unsigned char *(*make_key_fn) (const void *data_p, uint32 raw_key_length, uint32 *key_len_p), void (*free_key_and_value_fn) (unsigned char *key_p, void *value_p), server_rec *server_p, const char *mutex_filename_s, const char *cache_id_s, const char *provider_name_s)
{
	ap_socache_provider_t *provider_p = ap_lookup_provider (AP_SOCACHE_PROVIDER_GROUP, provider_name_s, AP_SOCACHE_PROVIDER_VERSION);

	if (provider_p)
		{
			apr_status_t status = apr_global_mutex_create (& (storage_p -> ags_mutex_p), mutex_filename_s, APR_THREAD_MUTEX_UNNESTED, pool_p);

			if (status == APR_SUCCESS)
				{
					char *current_dir_s = GetCurrentWorkingDirectory ();

					if (current_dir_s)
						{
							storage_p -> ags_largest_entry_memory_id = AllocateSharedMemory (current_dir_s, sizeof (unsigned int), 0644);

							FreeCopiedString (current_dir_s);

							if (storage_p -> ags_largest_entry_memory_id != -1)
								{
									storage_p -> ags_entries_p = apr_hash_make_custom (pool_p, hash_fn);

										if (storage_p -> ags_entries_p)
											{
												storage_p -> ags_pool_p = pool_p;
												storage_p -> ags_server_p = server_p;
												storage_p -> ags_make_key_fn = make_key_fn;
												storage_p -> ags_free_key_and_value_fn = free_key_and_value_fn;

												storage_p -> ags_cache_id_s = cache_id_s;
												storage_p -> ags_mutex_lock_filename_s = mutex_filename_s;

												storage_p -> ags_socache_instance_p = NULL;
												storage_p -> ags_socache_provider_p = provider_p;

												apr_pool_cleanup_register (pool_p, storage_p, (const void *) FreeAPRGlobalStorage, apr_pool_cleanup_null);

												return true;
											}		/* if (storage_p -> ags_entries_p) */
										else
											{
												PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to allocate shared memory hash table");
											}

									FreeSharedMemory (storage_p -> ags_largest_entry_memory_id);
								}		/* if (storage_p -> ags_largest_entry_memory_id != -1) */
							else
								{
									PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to allocate shared memory for largest chunk size");
								}

						}		/* if (mem_key_s) */
					else
						{
							PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to create memory key from \"%s\" and \".memory\"", cache_id_s);
						}

					apr_global_mutex_destroy (storage_p -> ags_mutex_p);
					storage_p -> ags_mutex_p = NULL;
				}		/* if (status == APR_SUCCESS) */
			else
				{
					PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to create global mutex for shared memory at %s", mutex_filename_s);
				}

		}		/* if (provider_p) */
	else
		{
			PrintErrors (STM_LEVEL_SEVERE, __FILE__, __LINE__, "Failed to find provider \"%s\"", provider_name_s ? provider_name_s : "NULL");
		}

	return false;
}
Пример #18
0
APR_DECLARE(apr_status_t) apr_dso_load(struct apr_dso_handle_t **res_handle, 
                                       const char *path, apr_pool_t *ctx)
{
    HINSTANCE os_handle;
    apr_status_t rv;
#ifndef _WIN32_WCE
    UINT em;
#endif

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE 
    {
        apr_wchar_t wpath[APR_PATH_MAX];
        if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) 
                                            / sizeof(apr_wchar_t), path))
                != APR_SUCCESS) {
            *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
            return ((*res_handle)->load_error = rv);
        }
        /* Prevent ugly popups from killing our app */
#ifndef _WIN32_WCE
        em = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif
        os_handle = LoadLibraryExW(wpath, NULL, 0);
        if (!os_handle)
            os_handle = LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
        if (!os_handle)
            rv = apr_get_os_error();
#ifndef _WIN32_WCE
        SetErrorMode(em);
#endif
    }
#endif /* APR_HAS_UNICODE_FS */
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
    {
        char fspec[APR_PATH_MAX], *p = fspec;
        /* Must convert path from / to \ notation.
         * Per PR2555, the LoadLibraryEx function is very picky about slashes.
         * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL.
         * LoadLibrary in the MS PSDK also reveals that it -explicitly- states
         * that backslashes must be used for the LoadLibrary family of calls.
         */
        apr_cpystrn(fspec, path, sizeof(fspec));
        while ((p = strchr(p, '/')) != NULL)
            *p = '\\';
        
        /* Prevent ugly popups from killing our app */
        em = SetErrorMode(SEM_FAILCRITICALERRORS);
        os_handle = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
        if (!os_handle)
            os_handle = LoadLibraryEx(path, NULL, 0);
        if (!os_handle)
            rv = apr_get_os_error();
        else
            rv = APR_SUCCESS;
        SetErrorMode(em);
    }
#endif

    *res_handle = apr_pcalloc(ctx, sizeof(**res_handle));
    (*res_handle)->cont = ctx;

    if (rv) {
        return ((*res_handle)->load_error = rv);
    }

    (*res_handle)->handle = (void*)os_handle;
    (*res_handle)->load_error = APR_SUCCESS;

    apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null);

    return APR_SUCCESS;
}
Пример #19
0
svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t *conn,
                                apr_pool_t *pool,
                                server_baton_t *b,
                                enum access_type required,
                                svn_boolean_t needs_username)
{
  sasl_conn_t *sasl_ctx;
  apr_pool_t *subpool;
  apr_status_t apr_err;
  const char *localaddrport = NULL, *remoteaddrport = NULL;
  const char *mechlist, *val;
  char hostname[APRMAXHOSTLEN + 1];
  sasl_security_properties_t secprops;
  svn_boolean_t success, no_anonymous;
  int mech_count, result = SASL_OK;

  SVN_ERR(svn_ra_svn__get_addresses(&localaddrport, &remoteaddrport,
                                        conn, pool));
  apr_err = apr_gethostname(hostname, sizeof(hostname), pool);
  if (apr_err)
    {
      svn_error_t *err = svn_error_wrap_apr(apr_err, _("Can't get hostname"));
      SVN_ERR(write_failure(conn, pool, &err));
      return svn_ra_svn_flush(conn, pool);
    }

  /* Create a SASL context. SASL_SUCCESS_DATA tells SASL that the protocol
     supports sending data along with the final "success" message. */
  result = sasl_server_new(SVN_RA_SVN_SASL_NAME,
                           hostname, b->realm,
                           localaddrport, remoteaddrport,
                           NULL, SASL_SUCCESS_DATA,
                           &sasl_ctx);
  if (result != SASL_OK)
    {
      svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                                          sasl_errstring(result, NULL, NULL));
      SVN_ERR(write_failure(conn, pool, &err));
      return svn_ra_svn_flush(conn, pool);
    }

  /* Make sure the context is always destroyed. */
  apr_pool_cleanup_register(b->pool, sasl_ctx, sasl_dispose_cb,
                            apr_pool_cleanup_null);

  /* Initialize security properties. */
  svn_ra_svn__default_secprops(&secprops);

  /* Don't allow ANONYMOUS if a username is required. */
  no_anonymous = needs_username || get_access(b, UNAUTHENTICATED) < required;
  if (no_anonymous)
    secprops.security_flags |= SASL_SEC_NOANONYMOUS;

  svn_config_get(b->cfg, &val,
                 SVN_CONFIG_SECTION_SASL,
                 SVN_CONFIG_OPTION_MIN_SSF,
                 "0");
  SVN_ERR(svn_cstring_atoui(&secprops.min_ssf, val));

  svn_config_get(b->cfg, &val,
                 SVN_CONFIG_SECTION_SASL,
                 SVN_CONFIG_OPTION_MAX_SSF,
                 "256");
  SVN_ERR(svn_cstring_atoui(&secprops.max_ssf, val));

  /* Set security properties. */
  result = sasl_setprop(sasl_ctx, SASL_SEC_PROPS, &secprops);
  if (result != SASL_OK)
    return fail_cmd(conn, pool, sasl_ctx);

  /* SASL needs to know if we are externally authenticated. */
  if (b->tunnel_user)
    result = sasl_setprop(sasl_ctx, SASL_AUTH_EXTERNAL, b->tunnel_user);
  if (result != SASL_OK)
    return fail_cmd(conn, pool, sasl_ctx);

  /* Get the list of mechanisms. */
  result = sasl_listmech(sasl_ctx, NULL, NULL, " ", NULL,
                         &mechlist, NULL, &mech_count);

  if (result != SASL_OK)
    return fail_cmd(conn, pool, sasl_ctx);

  if (mech_count == 0)
    {
      svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                                          _("Could not obtain the list"
                                          " of SASL mechanisms"));
      SVN_ERR(write_failure(conn, pool, &err));
      return svn_ra_svn_flush(conn, pool);
    }

  /* Send the list of mechanisms and the realm to the client. */
  SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "(w)c",
                                        mechlist, b->realm));

  /* The main authentication loop. */
  subpool = svn_pool_create(pool);
  do
    {
      svn_pool_clear(subpool);
      SVN_ERR(try_auth(conn, sasl_ctx, subpool, b, &success));
    }
  while (!success);
  svn_pool_destroy(subpool);

  SVN_ERR(svn_ra_svn__enable_sasl_encryption(conn, sasl_ctx, pool));

  if (no_anonymous)
    {
      char *p;
      const void *user;

      /* Get the authenticated username. */
      result = sasl_getprop(sasl_ctx, SASL_USERNAME, &user);

      if (result != SASL_OK)
        return fail_cmd(conn, pool, sasl_ctx);

      if ((p = strchr(user, '@')) != NULL)
        {
          /* Drop the realm part. */
          b->user = apr_pstrndup(b->pool, user, p - (const char *)user);
        }
      else
        {
          svn_error_t *err;
          err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
                                 _("Couldn't obtain the authenticated"
                                 " username"));
          SVN_ERR(write_failure(conn, pool, &err));
          return svn_ra_svn_flush(conn, pool);
        }
    }

  return SVN_NO_ERROR;
}
Пример #20
0
/*
 * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
 * either return an error to be displayed, or set *EXIT_CODE to non-zero and
 * return SVN_NO_ERROR.
 */
static svn_error_t *
sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
  enum run_mode run_mode = run_mode_unspecified;
  svn_boolean_t foreground = FALSE;
  apr_socket_t *sock;
  apr_sockaddr_t *sa;
  svn_error_t *err;
  apr_getopt_t *os;
  int opt;
  serve_params_t params;
  const char *arg;
  apr_status_t status;
#ifndef WIN32
  apr_proc_t proc;
#endif
  svn_boolean_t is_multi_threaded;
  enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
  svn_boolean_t cache_fulltexts = TRUE;
  svn_boolean_t cache_txdeltas = TRUE;
  svn_boolean_t cache_revprops = FALSE;
  svn_boolean_t use_block_read = FALSE;
  apr_uint16_t port = SVN_RA_SVN_PORT;
  const char *host = NULL;
  int family = APR_INET;
  apr_int32_t sockaddr_info_flags = 0;
#if APR_HAVE_IPV6
  svn_boolean_t prefer_v6 = FALSE;
#endif
  svn_boolean_t quiet = FALSE;
  svn_boolean_t is_version = FALSE;
  int mode_opt_count = 0;
  int handling_opt_count = 0;
  const char *config_filename = NULL;
  const char *pid_filename = NULL;
  const char *log_filename = NULL;
  svn_node_kind_t kind;
  apr_size_t min_thread_count = THREADPOOL_MIN_SIZE;
  apr_size_t max_thread_count = THREADPOOL_MAX_SIZE;
#ifdef SVN_HAVE_SASL
  SVN_ERR(cyrus_init(pool));
#endif

  /* Check library versions */
  SVN_ERR(check_lib_versions());

  /* Initialize the FS library. */
  SVN_ERR(svn_fs_initialize(pool));

  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

  params.root = "/";
  params.tunnel = FALSE;
  params.tunnel_user = NULL;
  params.read_only = FALSE;
  params.base = NULL;
  params.cfg = NULL;
  params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
  params.logger = NULL;
  params.config_pool = NULL;
  params.authz_pool = NULL;
  params.fs_config = NULL;
  params.vhost = FALSE;
  params.username_case = CASE_ASIS;
  params.memory_cache_size = (apr_uint64_t)-1;
  params.zero_copy_limit = 0;
  params.error_check_interval = 4096;

  while (1)
    {
      status = apr_getopt_long(os, svnserve__options, &opt, &arg);
      if (APR_STATUS_IS_EOF(status))
        break;
      if (status != APR_SUCCESS)
        {
          usage(argv[0], pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }
      switch (opt)
        {
        case '6':
#if APR_HAVE_IPV6
          prefer_v6 = TRUE;
#endif
          /* ### Maybe error here if we don't have IPV6 support? */
          break;

        case 'h':
          help(pool);
          return SVN_NO_ERROR;

        case 'q':
          quiet = TRUE;
          break;

        case SVNSERVE_OPT_VERSION:
          is_version = TRUE;
          break;

        case 'd':
          if (run_mode != run_mode_daemon)
            {
              run_mode = run_mode_daemon;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_FOREGROUND:
          foreground = TRUE;
          break;

        case SVNSERVE_OPT_SINGLE_CONN:
          handling_mode = connection_mode_single;
          handling_opt_count++;
          break;

        case 'i':
          if (run_mode != run_mode_inetd)
            {
              run_mode = run_mode_inetd;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_LISTEN_PORT:
          {
            apr_uint64_t val;

            err = svn_cstring_strtoui64(&val, arg, 0, APR_UINT16_MAX, 10);
            if (err)
              return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
                                       _("Invalid port '%s'"), arg);
            port = (apr_uint16_t)val;
          }
          break;

        case SVNSERVE_OPT_LISTEN_HOST:
          host = arg;
          break;

        case 't':
          if (run_mode != run_mode_tunnel)
            {
              run_mode = run_mode_tunnel;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_TUNNEL_USER:
          params.tunnel_user = arg;
          break;

        case 'X':
          if (run_mode != run_mode_listen_once)
            {
              run_mode = run_mode_listen_once;
              mode_opt_count++;
            }
          break;

        case 'r':
          SVN_ERR(svn_utf_cstring_to_utf8(&params.root, arg, pool));

          SVN_ERR(svn_io_check_resolved_path(params.root, &kind, pool));
          if (kind != svn_node_dir)
            {
              return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                       _("Root path '%s' does not exist "
                         "or is not a directory"), params.root);
            }

          params.root = svn_dirent_internal_style(params.root, pool);
          SVN_ERR(svn_dirent_get_absolute(&params.root, params.root, pool));
          break;

        case 'R':
          params.read_only = TRUE;
          break;

        case 'T':
          handling_mode = connection_mode_thread;
          handling_opt_count++;
          break;

        case 'c':
          params.compression_level = atoi(arg);
          if (params.compression_level < SVN_DELTA_COMPRESSION_LEVEL_NONE)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE;
          if (params.compression_level > SVN_DELTA_COMPRESSION_LEVEL_MAX)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_MAX;
          break;

        case 'M':
          params.memory_cache_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_CACHE_TXDELTAS:
          cache_txdeltas = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_FULLTEXTS:
          cache_fulltexts = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_REVPROPS:
          cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_BLOCK_READ:
          use_block_read = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CLIENT_SPEED:
          {
            apr_size_t bandwidth = (apr_size_t)apr_strtoi64(arg, NULL, 0);

            /* for slower clients, don't try anything fancy */
            if (bandwidth >= 1000)
              {
                /* block other clients for at most 1 ms (at full bandwidth).
                   Note that the send buffer is 16kB anyways. */
                params.zero_copy_limit = bandwidth * 120;

                /* check for aborted connections at the same rate */
                params.error_check_interval = bandwidth * 120;
              }
          }
          break;

        case SVNSERVE_OPT_MIN_THREADS:
          min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MAX_THREADS:
          max_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

#ifdef WIN32
        case SVNSERVE_OPT_SERVICE:
          if (run_mode != run_mode_service)
            {
              run_mode = run_mode_service;
              mode_opt_count++;
            }
          break;
#endif

        case SVNSERVE_OPT_CONFIG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&config_filename, arg, pool));
          config_filename = svn_dirent_internal_style(config_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&config_filename, config_filename,
                                          pool));
          break;

        case SVNSERVE_OPT_PID_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool));
          pid_filename = svn_dirent_internal_style(pid_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&pid_filename, pid_filename, pool));
          break;

         case SVNSERVE_OPT_VIRTUAL_HOST:
           params.vhost = TRUE;
           break;

         case SVNSERVE_OPT_LOG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&log_filename, arg, pool));
          log_filename = svn_dirent_internal_style(log_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&log_filename, log_filename, pool));
          break;

        }
    }

  if (is_version)
    {
      SVN_ERR(version(quiet, pool));
      return SVN_NO_ERROR;
    }

  if (os->ind != argc)
    {
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (mode_opt_count != 1)
    {
      svn_error_clear(svn_cmdline_fputs(
#ifdef WIN32
                      _("You must specify exactly one of -d, -i, -t, "
                        "--service or -X.\n"),
#else
                      _("You must specify exactly one of -d, -i, -t or -X.\n"),
#endif
                       stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (handling_opt_count > 1)
    {
      svn_error_clear(svn_cmdline_fputs(
                      _("You may only specify one of -T or --single-thread\n"),
                      stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  /* construct object pools */
  is_multi_threaded = handling_mode == connection_mode_thread;
  params.fs_config = apr_hash_make(pool);
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
                cache_txdeltas ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                cache_fulltexts ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                cache_revprops ? "2" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ,
                use_block_read ? "1" :"0");

  SVN_ERR(svn_repos__config_pool_create(&params.config_pool,
                                        is_multi_threaded,
                                        pool));
  SVN_ERR(svn_repos__authz_pool_create(&params.authz_pool,
                                       params.config_pool,
                                       is_multi_threaded,
                                       pool));

  /* If a configuration file is specified, load it and any referenced
   * password and authorization files. */
  if (config_filename)
    {
      params.base = svn_dirent_dirname(config_filename, pool);

      SVN_ERR(svn_repos__config_pool_get(&params.cfg, NULL,
                                         params.config_pool,
                                         config_filename,
                                         TRUE, /* must_exist */
                                         FALSE, /* names_case_sensitive */
                                         NULL,
                                         pool));
    }

  if (log_filename)
    SVN_ERR(logger__create(&params.logger, log_filename, pool));
  else if (run_mode == run_mode_listen_once)
    SVN_ERR(logger__create_for_stderr(&params.logger, pool));

  if (params.tunnel_user && run_mode != run_mode_tunnel)
    {
      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
               _("Option --tunnel-user is only valid in tunnel mode"));
    }

  if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
    {
      apr_pool_t *connection_pool;
      svn_ra_svn_conn_t *conn;
      svn_stream_t *stdin_stream;
      svn_stream_t *stdout_stream;

      params.tunnel = (run_mode == run_mode_tunnel);
      apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
                                redirect_stdout);

      SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool));
      SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

      /* Use a subpool for the connection to ensure that if SASL is used
       * the pool cleanup handlers that call sasl_dispose() (connection_pool)
       * and sasl_done() (pool) are run in the right order. See issue #3664. */
      connection_pool = svn_pool_create(pool);
      conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream,
                                     params.compression_level,
                                     params.zero_copy_limit,
                                     params.error_check_interval,
                                     connection_pool);
      err = serve(conn, &params, connection_pool);
      svn_pool_destroy(connection_pool);

      return err;
    }

#ifdef WIN32
  /* If svnserve needs to run as a Win32 service, then we need to
     coordinate with the Service Control Manager (SCM) before
     continuing.  This function call registers the svnserve.exe
     process with the SCM, waits for the "start" command from the SCM
     (which will come very quickly), and confirms that those steps
     succeeded.

     After this call succeeds, the service is free to run.  At some
     point in the future, the SCM will send a message to the service,
     requesting that it stop.  This is translated into a call to
     winservice_notify_stop().  The service is then responsible for
     cleanly terminating.

     We need to do this before actually starting the service logic
     (opening files, sockets, etc.) because the SCM wants you to
     connect *first*, then do your service-specific logic.  If the
     service process takes too long to connect to the SCM, then the
     SCM will decide that the service is busted, and will give up on
     it.
     */
  if (run_mode == run_mode_service)
    {
      err = winservice_start();
      if (err)
        {
          svn_handle_error2(err, stderr, FALSE, "svnserve: ");

          /* This is the most common error.  It means the user started
             svnserve from a shell, and specified the --service
             argument.  svnserve cannot be started, as a service, in
             this way.  The --service argument is valid only valid if
             svnserve is started by the SCM. */
          if (err->apr_err ==
              APR_FROM_OS_ERROR(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT))
            {
              svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                  _("svnserve: The --service flag is only valid if the"
                    " process is started by the Service Control Manager.\n")));
            }

          svn_error_clear(err);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }

      /* The service is now in the "starting" state.  Before the SCM will
         consider the service "started", this thread must call the
         winservice_running() function. */
    }
#endif /* WIN32 */

  /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get
     APR_UNSPEC, because it may give us back an IPV6 address even if we can't
     create IPV6 sockets. */

#if APR_HAVE_IPV6
#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status == 0)
    {
      apr_socket_close(sock);
      family = APR_UNSPEC;

      if (prefer_v6)
        {
          if (host == NULL)
            host = "::";
          sockaddr_info_flags = APR_IPV6_ADDR_OK;
        }
      else
        {
          if (host == NULL)
            host = "0.0.0.0";
          sockaddr_info_flags = APR_IPV4_ADDR_OK;
        }
    }
#endif

  status = apr_sockaddr_info_get(&sa, host, family, port,
                                 sockaddr_info_flags, pool);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't get address info"));
    }


#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't create server socket"));
    }

  /* Prevents "socket in use" errors when server is killed and quickly
   * restarted. */
  status = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't set options on server socket"));
    }

  status = apr_socket_bind(sock, sa);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't bind server socket"));
    }

  status = apr_socket_listen(sock, ACCEPT_BACKLOG);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't listen on server socket"));
    }

#if APR_HAS_FORK
  if (run_mode != run_mode_listen_once && !foreground)
    /* ### ignoring errors... */
    apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);

  apr_signal(SIGCHLD, sigchld_handler);
#endif

#ifdef SIGPIPE
  /* Disable SIGPIPE generation for the platforms that have it. */
  apr_signal(SIGPIPE, SIG_IGN);
#endif

#ifdef SIGXFSZ
  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
   * working with large files when compiled against an APR that doesn't have
   * large file support will crash the program, which is uncool. */
  apr_signal(SIGXFSZ, SIG_IGN);
#endif

  if (pid_filename)
    SVN_ERR(write_pid_file(pid_filename, pool));

#ifdef WIN32
  status = apr_os_sock_get(&winservice_svnserve_accept_socket, sock);
  if (status)
    winservice_svnserve_accept_socket = INVALID_SOCKET;

  /* At this point, the service is "running".  Notify the SCM. */
  if (run_mode == run_mode_service)
    winservice_running();
#endif

  /* Configure FS caches for maximum efficiency with svnserve.
   * For pre-forked (i.e. multi-processed) mode of operation,
   * keep the per-process caches smaller than the default.
   * Also, apply the respective command line parameters, if given. */
  {
    svn_cache_config_t settings = *svn_cache_config_get();

    if (params.memory_cache_size != -1)
      settings.cache_size = params.memory_cache_size;

    settings.single_threaded = TRUE;
    if (handling_mode == connection_mode_thread)
      {
#if APR_HAS_THREADS
        settings.single_threaded = FALSE;
#else
        /* No requests will be processed at all
         * (see "switch (handling_mode)" code further down).
         * But if they were, some other synchronization code
         * would need to take care of securing integrity of
         * APR-based structures. That would include our caches.
         */
#endif
      }

    svn_cache_config_set(&settings);
  }

#if APR_HAS_THREADS
  SVN_ERR(svn_root_pools__create(&connection_pools));

  if (handling_mode == connection_mode_thread)
    {
      /* create the thread pool with a valid range of threads */
      if (max_thread_count < 1)
        max_thread_count = 1;
      if (min_thread_count > max_thread_count)
        min_thread_count = max_thread_count;

      status = apr_thread_pool_create(&threads,
                                      min_thread_count,
                                      max_thread_count,
                                      pool);
      if (status)
        {
          return svn_error_wrap_apr(status, _("Can't create thread pool"));
        }

      /* let idle threads linger for a while in case more requests are
         coming in */
      apr_thread_pool_idle_wait_set(threads, THREADPOOL_THREAD_IDLE_LIMIT);

      /* don't queue requests unless we reached the worker thread limit */
      apr_thread_pool_threshold_set(threads, 0);
    }
  else
    {
      threads = NULL;
    }
#endif

  while (1)
    {
      connection_t *connection = NULL;
      SVN_ERR(accept_connection(&connection, sock, &params, handling_mode,
                                pool));
      if (run_mode == run_mode_listen_once)
        {
          err = serve_socket(connection, connection->pool);
          close_connection(connection);
          return err;
        }

      switch (handling_mode)
        {
        case connection_mode_fork:
#if APR_HAS_FORK
          status = apr_proc_fork(&proc, connection->pool);
          if (status == APR_INCHILD)
            {
              /* the child would't listen to the main server's socket */
              apr_socket_close(sock);

              /* serve_socket() logs any error it returns, so ignore it. */
              svn_error_clear(serve_socket(connection, connection->pool));
              close_connection(connection);
              return SVN_NO_ERROR;
            }
          else if (status != APR_INPARENT)
            {
              err = svn_error_wrap_apr(status, "apr_proc_fork");
              logger__log_error(params.logger, err, NULL, NULL);
              svn_error_clear(err);
            }
#endif
          break;

        case connection_mode_thread:
          /* Create a detached thread for each connection.  That's not a
             particularly sophisticated strategy for a threaded server, it's
             little different from forking one process per connection. */
#if APR_HAS_THREADS
          attach_connection(connection);

          status = apr_thread_pool_push(threads, serve_thread, connection,
                                        0, NULL);
          if (status)
            {
              return svn_error_wrap_apr(status, _("Can't push task"));
            }
#endif
          break;

        case connection_mode_single:
          /* Serve one connection at a time. */
          /* serve_socket() logs any error it returns, so ignore it. */
          svn_error_clear(serve_socket(connection, connection->pool));
        }

      close_connection(connection);
    }

  /* NOTREACHED */
}
Пример #21
0
/**
 * @brief Initialise a context for decrypting arbitrary data using the given key.
 * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
 *       *ctx is not NULL, *ctx must point at a previously created structure.
 * @param ctx The block context returned, see note.
 * @param blockSize The block size of the cipher.
 * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
 *           an IV will be created at random, in space allocated from the pool.
 *           If the buffer is not NULL, the IV in the buffer will be used.
 * @param key The key structure.
 * @param p The pool to use.
 * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
 *         Returns APR_EINIT if the backend failed to initialise the context. Returns
 *         APR_ENOTIMPL if not implemented.
 */
static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
        apr_size_t *blockSize, const unsigned char *iv,
        const apr_crypto_key_t *key, apr_pool_t *p)
{
    apr_crypto_config_t *config = key->f->config;
    apr_crypto_block_t *block = *ctx;
    if (!block) {
        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
    }
    if (!block) {
        return APR_ENOMEM;
    }
    block->f = key->f;
    block->pool = p;
    block->provider = key->provider;

    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
            apr_pool_cleanup_null);

    /* create a new context for encryption */
    EVP_CIPHER_CTX_init(&block->cipherCtx);
    block->initialised = 1;

    /* generate an IV, if necessary */
    if (key->ivSize) {
        if (iv == NULL) {
            return APR_ENOIV;
        }
    }

    /* set up our encryption context */
#if CRYPTO_OPENSSL_CONST_BUFFERS
    if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine,
            key->key, iv)) {
#else
        if (!EVP_DecryptInit_ex(&block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
#endif
        return APR_EINIT;
    }

    /* Clear up any read padding */
    if (!EVP_CIPHER_CTX_set_padding(&block->cipherCtx, key->doPad)) {
        return APR_EPADDING;
    }

    if (blockSize) {
        *blockSize = EVP_CIPHER_block_size(key->cipher);
    }

    return APR_SUCCESS;

}

/**
 * @brief Decrypt data provided by in, write it to out.
 * @note The number of bytes written will be written to outlen. If
 *       out is NULL, outlen will contain the maximum size of the
 *       buffer needed to hold the data, including any data
 *       generated by apr_crypto_block_decrypt_finish below. If *out points
 *       to NULL, a buffer sufficiently large will be created from
 *       the pool provided. If *out points to a not-NULL value, this
 *       value will be used as a buffer instead.
 * @param out Address of a buffer to which data will be written,
 *        see note.
 * @param outlen Length of the output will be written here.
 * @param in Address of the buffer to read.
 * @param inlen Length of the buffer to read.
 * @param ctx The block context to use.
 * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
 *         not implemented.
 */
static apr_status_t crypto_block_decrypt(unsigned char **out,
        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
        apr_crypto_block_t *ctx)
{
    int outl = *outlen;
    unsigned char *buffer;

    /* are we after the maximum size of the out buffer? */
    if (!out) {
        *outlen = inlen + EVP_MAX_BLOCK_LENGTH;
        return APR_SUCCESS;
    }

    /* must we allocate the output buffer from a pool? */
    if (!(*out)) {
        buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH);
        if (!buffer) {
            return APR_ENOMEM;
        }
        apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
        *out = buffer;
    }

#if CRYPT_OPENSSL_CONST_BUFFERS
    if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, in, inlen)) {
#else
    if (!EVP_DecryptUpdate(&ctx->cipherCtx, *out, &outl, (unsigned char *) in,
            inlen)) {
#endif
        return APR_ECRYPT;
    }
    *outlen = outl;

    return APR_SUCCESS;

}

/**
 * @brief Decrypt final data block, write it to out.
 * @note If necessary the final block will be written out after being
 *       padded. Typically the final block will be written to the
 *       same buffer used by apr_crypto_block_decrypt, offset by the
 *       number of bytes returned as actually written by the
 *       apr_crypto_block_decrypt() call. After this call, the context
 *       is cleaned and can be reused by apr_crypto_block_decrypt_init().
 * @param out Address of a buffer to which data will be written. This
 *            buffer must already exist, and is usually the same
 *            buffer used by apr_evp_crypt(). See note.
 * @param outlen Length of the output will be written here.
 * @param ctx The block context to use.
 * @return APR_ECRYPT if an error occurred.
 * @return APR_EPADDING if padding was enabled and the block was incorrectly
 *         formatted.
 * @return APR_ENOTIMPL if not implemented.
 */
static apr_status_t crypto_block_decrypt_finish(unsigned char *out,
        apr_size_t *outlen, apr_crypto_block_t *ctx)
{

    int len = *outlen;

    if (EVP_DecryptFinal_ex(&ctx->cipherCtx, out, &len) == 0) {
        return APR_EPADDING;
    }
    *outlen = len;

    return APR_SUCCESS;

}
Пример #22
0
Файл: pipe.c Проект: cmjonze/apr
APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool)
{
    ULONG filedes[2];
    ULONG rc, action;
    static int id = 0;
    char pipename[50];

    sprintf(pipename, "/pipe/%d.%d", getpid(), id++);
    rc = DosCreateNPipe(pipename, filedes, NP_ACCESS_INBOUND, NP_NOWAIT|1, 4096, 4096, 0);

    if (rc)
        return APR_FROM_OS_ERROR(rc);

    rc = DosConnectNPipe(filedes[0]);

    if (rc && rc != ERROR_PIPE_NOT_CONNECTED) {
        DosClose(filedes[0]);
        return APR_FROM_OS_ERROR(rc);
    }

    rc = DosOpen (pipename, filedes+1, &action, 0, FILE_NORMAL,
                  OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW,
                  OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
                  NULL);

    if (rc) {
        DosClose(filedes[0]);
        return APR_FROM_OS_ERROR(rc);
    }

    (*in) = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t));
    rc = DosCreateEventSem(NULL, &(*in)->pipeSem, DC_SEM_SHARED, FALSE);

    if (rc) {
        DosClose(filedes[0]);
        DosClose(filedes[1]);
        return APR_FROM_OS_ERROR(rc);
    }

    rc = DosSetNPipeSem(filedes[0], (HSEM)(*in)->pipeSem, 1);

    if (!rc) {
        rc = DosSetNPHState(filedes[0], NP_WAIT);
    }

    if (rc) {
        DosClose(filedes[0]);
        DosClose(filedes[1]);
        DosCloseEventSem((*in)->pipeSem);
        return APR_FROM_OS_ERROR(rc);
    }

    (*in)->pool = pool;
    (*in)->filedes = filedes[0];
    (*in)->fname = apr_pstrdup(pool, pipename);
    (*in)->isopen = TRUE;
    (*in)->buffered = FALSE;
    (*in)->flags = APR_FOPEN_READ;
    (*in)->pipe = 1;
    (*in)->timeout = -1;
    (*in)->blocking = BLK_ON;
    (*in)->ungetchar = -1;
    apr_pool_cleanup_register(pool, *in, apr_file_cleanup, apr_pool_cleanup_null);

    (*out) = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t));
    rc = DosCreateEventSem(NULL, &(*out)->pipeSem, DC_SEM_SHARED, FALSE);

    if (rc) {
        DosClose(filedes[0]);
        DosClose(filedes[1]);
        DosCloseEventSem((*in)->pipeSem);
        return APR_FROM_OS_ERROR(rc);
    }

    rc = DosSetNPipeSem(filedes[1], (HSEM)(*out)->pipeSem, 1);

    if (rc) {
        DosClose(filedes[0]);
        DosClose(filedes[1]);
        DosCloseEventSem((*in)->pipeSem);
        DosCloseEventSem((*out)->pipeSem);
        return APR_FROM_OS_ERROR(rc);
    }

    (*out)->pool = pool;
    (*out)->filedes = filedes[1];
    (*out)->fname = apr_pstrdup(pool, pipename);
    (*out)->isopen = TRUE;
    (*out)->buffered = FALSE;
    (*out)->flags = APR_FOPEN_WRITE;
    (*out)->pipe = 1;
    (*out)->timeout = -1;
    (*out)->blocking = BLK_ON;
    (*out)->ungetchar = -1;
    apr_pool_cleanup_register(pool, *out, apr_file_cleanup, apr_pool_cleanup_null);

    return APR_SUCCESS;
}
Пример #23
0
apr_status_t proc_spawn_process(const char *cmdline, fcgid_proc_info *procinfo,
                                fcgid_procnode *procnode)
{
    HANDLE *finish_event, listen_handle;
    SECURITY_ATTRIBUTES SecurityAttributes;
    fcgid_server_conf *sconf;
    apr_procattr_t *proc_attr;
    apr_status_t rv;
    apr_file_t *file;
    const char * const *proc_environ;
    char sock_path[FCGID_PATH_MAX];
    int argc;
    char const * wargv[APACHE_ARG_MAX + 1], *word; /* For wrapper */
    const char *tmp;

    /* Build wrapper args */
    argc = 0;
    tmp = cmdline;
    while (1) {
        word = ap_getword_white(procnode->proc_pool, &tmp);
        if (word == NULL || *word == '\0')
            break;
        if (argc >= APACHE_ARG_MAX)
            break;
        wargv[argc++] = word;
    }
    wargv[argc] = NULL;

    memset(&SecurityAttributes, 0, sizeof(SecurityAttributes));

    /* Prepare finish event */
    finish_event = apr_palloc(procnode->proc_pool, sizeof(HANDLE));
    *finish_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (*finish_event == NULL
        || !SetHandleInformation(*finish_event, HANDLE_FLAG_INHERIT, TRUE))
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create mutex for subprocess");
        return APR_ENOLOCK;
    }
    apr_pool_cleanup_register(procnode->proc_pool, finish_event,
                              close_finish_event, apr_pool_cleanup_null);

    /* For proc_kill_gracefully() */
    apr_pool_userdata_set(finish_event, FINISH_EVENT_DATA_NAME,
                          NULL, procnode->proc_pool);

    /* Pass the finish event id to subprocess */
    apr_table_setn(procinfo->proc_environ, SHUTDOWN_EVENT_NAME,
                   apr_ltoa(procnode->proc_pool, (long) *finish_event));

    /* Prepare the listen namedpipe file name (no check for truncation) */
    apr_snprintf(sock_path, sizeof sock_path,
                 "\\\\.\\pipe\\fcgidpipe-%lu.%d",
                 GetCurrentProcessId(), g_process_counter++);

    /* Prepare the listen namedpipe handle */
    SecurityAttributes.bInheritHandle = TRUE;
    SecurityAttributes.nLength = sizeof(SecurityAttributes);
    SecurityAttributes.lpSecurityDescriptor = NULL;
    listen_handle = CreateNamedPipe(sock_path,
                                    PIPE_ACCESS_DUPLEX,
                                    PIPE_TYPE_BYTE | PIPE_READMODE_BYTE |
                                    PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
                                    8192, 8192, 0, &SecurityAttributes);
    if (listen_handle == INVALID_HANDLE_VALUE) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't create namedpipe for subprocess");
        return APR_ENOSOCKET;
    }
    apr_cpystrn(procnode->socket_path, sock_path, sizeof(procnode->socket_path));
    apr_cpystrn(procnode->executable_path, wargv[0],
                sizeof(procnode->executable_path));

    /* Build environment variables */
    proc_environ = (const char * const *)
                   ap_create_environment(procnode->proc_pool,
                                         procinfo->proc_environ);
    if (!proc_environ) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     procinfo->main_server,
                     "mod_fcgid: can't build environment variables");
        return APR_ENOMEM;
    }

    /* Create process now */
    if ((rv = apr_procattr_create(&proc_attr, procnode->proc_pool))
               != APR_SUCCESS
        || (rv = apr_procattr_dir_set(proc_attr,
                     ap_make_dirstr_parent(procnode->proc_pool,
                                           wargv[0]))) != APR_SUCCESS
        || (rv = apr_procattr_cmdtype_set(proc_attr, APR_PROGRAM))
               != APR_SUCCESS
        || (rv = apr_procattr_detach_set(proc_attr, 1)) != APR_SUCCESS
        || (rv = apr_procattr_io_set(proc_attr, APR_NO_PIPE,
                                     APR_NO_FILE, APR_NO_FILE)) != APR_SUCCESS
        || (rv = apr_os_file_put(&file, &listen_handle, 0,
                                 procnode->proc_pool)) != APR_SUCCESS
        || (rv = apr_procattr_child_in_set(proc_attr, file, NULL))
               != APR_SUCCESS)
    {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, procinfo->main_server,
                     "mod_fcgid: can't create FastCGI process attribute");
        CloseHandle(listen_handle);
        return APR_ENOPROC;
    }

    /* fork and exec now */
    rv = apr_proc_create(&(procnode->proc_id), wargv[0], wargv,
                         proc_environ,
                         proc_attr, procnode->proc_pool);

    /* OK, I created the process, now put it back to idle list */
    CloseHandle(listen_handle);

    if (rv != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, procinfo->main_server,
                     "mod_fcgid: can't run %s", wargv[0]);
        return rv;
    }

    /* FcgidWin32PreventOrphans feature */
    sconf = ap_get_module_config(procinfo->main_server->module_config,
                                 &fcgid_module);

    if (sconf->hJobObjectForAutoCleanup != NULL) {
        /* Associate cgi process to current process */
        if (AssignProcessToJobObject(sconf->hJobObjectForAutoCleanup,
                                     procnode->proc_id.hproc) == 0) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                         procinfo->main_server,
                         "mod_fcgid: unable to assign child process to "
                         "job object");
        }
    }

    return APR_SUCCESS;
}
/* similar to authenticate a basic user, here the authentication is done for the user
   who opted for a secure SSPI authentication */
int authenticate_sspi_user(request_rec *r) 
{
	sspi_auth_ctx ctx;
    const char *current_auth;
	int res;

  	/* is SSPI authentication supported? */
	current_auth = ap_auth_type(r);
	if (!current_auth || strcasecmp(current_auth, "SSPI")) {
		return DECLINED;
	}

    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, SSPILOGNO(00001) "Entering authenticate_sspi_user()");

#ifdef _DEBUG
	if (sspiModuleInfo.currentlyDebugging == FALSE) {
		sspiModuleInfo.currentlyDebugging = TRUE;
		DebugBreak();
	}
#endif /* def _DEBUG */

	/* securezeromemory is needed so that the password is no longer present in the memory
	   this is needed otherwise someone else can read the decrypted password */
	SecureZeroMemory(&ctx, sizeof (ctx));

	ctx.r = r;
    ctx.crec = get_sspi_config_rec(r);

	if (!ctx.crec->sspi_on) {

	    ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00007)
		    "access to %s declined, reason: SSPIAuth is off",
		    r->uri);

		return DECLINED;
	}

	/* checking all the different conditons */
	if (sspiModuleInfo.supportsSSPI == FALSE) {
		if (ctx.crec->sspi_authoritative) {

			ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00002)
				"access to %s failed, reason: SSPI support is not available",
				r->uri);

			return HTTP_INTERNAL_SERVER_ERROR;
		} else {

	        ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, SSPILOGNO(00008)
		        "access to %s declined, reason: SSPIAuth support is not available",
		        r->uri);

			return DECLINED;
		}
	}

	/* checking all the different conditons */
	if (ctx.crec->sspi_package_basic == NULL) {
		ctx.crec->sspi_package_basic = ctx.crec->sspi_packages;

		if (ctx.crec->sspi_package_basic == NULL) {
			ctx.crec->sspi_package_basic = sspiModuleInfo.defaultPackage;
		}
	}

	if (ctx.crec->sspi_packages == NULL) {
		ctx.crec->sspi_packages = ctx.crec->sspi_package_basic;
	}

	apr_pool_userdata_get(&ctx.scr, sspiModuleInfo.userDataKeyString, r->connection->pool);

	if (ctx.scr == NULL) {
		ctx.scr = apr_pcalloc(r->connection->pool, sizeof(sspi_connection_rec));
		apr_pool_userdata_setn(ctx.scr, sspiModuleInfo.userDataKeyString, cleanup_sspi_connection, 
			r->connection->pool);
	}
	else if (ie_post_needs_reauth(&ctx)) {
		// Internet Explorer wants to re authenticate, not POST
		ctx.scr->username = NULL;

		if (ctx.scr->server_context.dwLower ||
				ctx.scr->server_context.dwUpper) {
			sspiModuleInfo.functable->DeleteSecurityContext(&ctx.scr->server_context);
			ctx.scr->server_context.dwLower = 0;
			ctx.scr->server_context.dwUpper = 0;
			
			ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
				"SSPI:	starting IE re authentication");
		}
	}

	if (ctx.scr->username == NULL) {

		if (res = get_sspi_header(&ctx)) {
			if (!ie_post_empty(&ctx) &&
				ctx.crec->sspi_optional) {
				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
					"SSPI: Optional auth exercised phase 1");
				ctx.r->user = "NT AUTHORITY\\ANONYMOUS LOGON";
				ctx.r->ap_auth_type = "Basic";
				return OK;
			}
			return res;
		}

		if ((! ctx.scr->have_credentials) && 
			(res = obtain_credentials(&ctx))) {
			if (!ie_post_empty(&ctx) &&
				ctx.crec->sspi_optional) {
				ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
					"SSPI: Optional auth exercised phase 2");
				ctx.r->user = "NT AUTHORITY\\ANONYMOUS LOGON";
				ctx.r->ap_auth_type = "Basic";
				return OK;
			}
			return res;
		}

		if (ctx.hdr.authtype == typeSSPI) {

			if (res = accept_security_context(&ctx)) {
				if (!ie_post_empty(&ctx) &&
					ctx.crec->sspi_optional) {
					ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
						"SSPI: Optional auth exercised phase 3");
					ctx.r->user = "NT AUTHORITY\\ANONYMOUS LOGON";
					ctx.r->ap_auth_type = "Basic";
					return OK;
				}
				return res;
			}
		} else if (ctx.hdr.authtype == typeBasic) {
			res = check_cleartext_auth(&ctx);
			/* don't forget to clean up open user password */
			SecureZeroMemory(&ctx.hdr, sizeof(ctx.hdr));
			if (res) {
				return res;
			}
		}

		/* we should stick with per-request auth - per connection can cause 
		* problems with POSTing and would be difficult to code such that different
		* configs were allowed on the same connection (eg. CGI that referred to 
		* images in another directory. */
		if (ctx.crec->sspi_per_request_auth) {
			apr_pool_cleanup_kill(r->connection->pool, ctx.scr, cleanup_sspi_connection);
			apr_pool_cleanup_register(r->pool, ctx.scr, cleanup_sspi_connection, apr_pool_cleanup_null);
		}
	}

	if (res = set_connection_details(&ctx)) {
		return res;
	}
	/* logging */
	ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, SSPILOGNO(00009)
		"Authenticated user: %s", r->user);

	return OK;
}
Пример #25
0
Файл: shm.c Проект: ATCP/mtcp
APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
                                         const char *file,
                                         apr_pool_t *pool)
{
    HANDLE hMap;
    void *mapkey;
    void *base;

    if (!file) {
        return APR_EINVAL;
    }
    else {
        /* res_name_from_filename turns file into a pseudo-name
         * without slashes or backslashes, and prepends the \global
         * prefix on Win2K and later
         */
        mapkey = res_name_from_filename(file, 1, pool);
    }

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
    {
#ifndef _WIN32_WCE
        hMap = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
#else
        /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with
         * opening the existing shmem and reading its size from the header 
         */
        hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
                                  PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey);
#endif
    }
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
    {
        hMap = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey);
    }
#endif

    if (!hMap) {
        return apr_get_os_error();
    }
    
    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    if (!base) {
        CloseHandle(hMap);
        return apr_get_os_error();
    }
    
    *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
    (*m)->pool = pool;
    (*m)->memblk = base;
    /* Real (*m)->mem->size could be recovered with VirtualQuery */
    (*m)->size = (*m)->memblk->size;
#if _WIN32_WCE
    /* Reopen with real size  */
    UnmapViewOfFile(base);
    CloseHandle(hMap);

    hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, 
                              PAGE_READWRITE, 0, (*m)->size, mapkey);
    if (!hMap) {
        return apr_get_os_error();
    }
    base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    if (!base) {
        CloseHandle(hMap);
        return apr_get_os_error();
    }    
#endif
    (*m)->hMap = hMap;
    (*m)->length = (*m)->memblk->length;
    (*m)->usrmem = (char*)base + sizeof(memblock_t);
    (*m)->filename = NULL;

    apr_pool_cleanup_register((*m)->pool, *m, 
                              shm_cleanup, apr_pool_cleanup_null);
    return APR_SUCCESS;
}
Пример #26
0
static apr_status_t proc_mutex_proc_pthread_create(apr_proc_mutex_t *new_mutex,
                                                   const char *fname)
{
    apr_status_t rv;
    int fd;
    pthread_mutexattr_t mattr;

    fd = open("/dev/zero", O_RDWR);
    if (fd < 0) {
        return errno;
    }

    new_mutex->pthread_interproc = (pthread_mutex_t *)mmap(
                                       (caddr_t) 0, 
                                       sizeof(pthread_mutex_t), 
                                       PROT_READ | PROT_WRITE, MAP_SHARED,
                                       fd, 0); 
    if (new_mutex->pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) {
        close(fd);
        return errno;
    }
    close(fd);

    new_mutex->curr_locked = -1; /* until the mutex has been created */

    if ((rv = pthread_mutexattr_init(&mattr))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        return rv;
    }
    if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        pthread_mutexattr_destroy(&mattr);
        return rv;
    }

#ifdef HAVE_PTHREAD_MUTEX_ROBUST
    if ((rv = pthread_mutexattr_setrobust_np(&mattr, 
                                               PTHREAD_MUTEX_ROBUST_NP))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        pthread_mutexattr_destroy(&mattr);
        return rv;
    }
    if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        pthread_mutexattr_destroy(&mattr);
        return rv;
    }
#endif /* HAVE_PTHREAD_MUTEX_ROBUST */

    if ((rv = pthread_mutex_init(new_mutex->pthread_interproc, &mattr))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        pthread_mutexattr_destroy(&mattr);
        return rv;
    }

    new_mutex->curr_locked = 0; /* mutex created now */

    if ((rv = pthread_mutexattr_destroy(&mattr))) {
#ifdef HAVE_ZOS_PTHREADS
        rv = errno;
#endif
        proc_mutex_proc_pthread_cleanup(new_mutex);
        return rv;
    }

    apr_pool_cleanup_register(new_mutex->pool,
                              (void *)new_mutex,
                              apr_proc_mutex_cleanup, 
                              apr_pool_cleanup_null);
    return APR_SUCCESS;
}
Пример #27
0
/* Depending on CREATE, create or open the environment and databases
   for filesystem FS in PATH. Use POOL for temporary allocations. */
static svn_error_t *
open_databases(svn_fs_t *fs,
               svn_boolean_t create,
               int format,
               const char *path,
               apr_pool_t *pool)
{
  base_fs_data_t *bfd;

  SVN_ERR(svn_fs__check_fs(fs, FALSE));

  bfd = apr_pcalloc(fs->pool, sizeof(*bfd));
  fs->vtable = &fs_vtable;
  fs->fsap_data = bfd;

  /* Initialize the fs's path. */
  fs->path = apr_pstrdup(fs->pool, path);

  if (create)
    SVN_ERR(bdb_write_config(fs));

  /* Create the Berkeley DB environment.  */
  {
    svn_error_t *err = svn_fs_bdb__open(&(bfd->bdb), path,
                                        SVN_BDB_STANDARD_ENV_FLAGS,
                                        0666, fs->pool);
    if (err)
      {
        if (create)
          return svn_error_createf
            (err->apr_err, err,
             _("Berkeley DB error for filesystem '%s'"
               " while creating environment:\n"),
             fs->path);
        else
          return svn_error_createf
            (err->apr_err, err,
             _("Berkeley DB error for filesystem '%s'"
               " while opening environment:\n"),
             fs->path);
      }
  }

  /* We must register the FS cleanup function *after* opening the
     environment, so that it's run before the environment baton
     cleanup. */
  apr_pool_cleanup_register(fs->pool, fs, cleanup_fs_apr,
                            apr_pool_cleanup_null);


  /* Create the databases in the environment.  */
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'nodes' table")
                        : N_("opening 'nodes' table")),
                   svn_fs_bdb__open_nodes_table(&bfd->nodes,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'revisions' table")
                        : N_("opening 'revisions' table")),
                   svn_fs_bdb__open_revisions_table(&bfd->revisions,
                                                    bfd->bdb->env,
                                                    create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'transactions' table")
                        : N_("opening 'transactions' table")),
                   svn_fs_bdb__open_transactions_table(&bfd->transactions,
                                                       bfd->bdb->env,
                                                       create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'copies' table")
                        : N_("opening 'copies' table")),
                   svn_fs_bdb__open_copies_table(&bfd->copies,
                                                 bfd->bdb->env,
                                                 create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'changes' table")
                        : N_("opening 'changes' table")),
                   svn_fs_bdb__open_changes_table(&bfd->changes,
                                                  bfd->bdb->env,
                                                  create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'representations' table")
                        : N_("opening 'representations' table")),
                   svn_fs_bdb__open_reps_table(&bfd->representations,
                                               bfd->bdb->env,
                                               create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'strings' table")
                        : N_("opening 'strings' table")),
                   svn_fs_bdb__open_strings_table(&bfd->strings,
                                                  bfd->bdb->env,
                                                  create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'uuids' table")
                        : N_("opening 'uuids' table")),
                   svn_fs_bdb__open_uuids_table(&bfd->uuids,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'locks' table")
                        : N_("opening 'locks' table")),
                   svn_fs_bdb__open_locks_table(&bfd->locks,
                                                bfd->bdb->env,
                                                create)));
  SVN_ERR(BDB_WRAP(fs, (create
                        ? N_("creating 'lock-tokens' table")
                        : N_("opening 'lock-tokens' table")),
                   svn_fs_bdb__open_lock_tokens_table(&bfd->lock_tokens,
                                                      bfd->bdb->env,
                                                      create)));

  if (format >= SVN_FS_BASE__MIN_NODE_ORIGINS_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? N_("creating 'node-origins' table")
                            : N_("opening 'node-origins' table")),
                       svn_fs_bdb__open_node_origins_table(&bfd->node_origins,
                                                           bfd->bdb->env,
                                                           create)));
    }

  if (format >= SVN_FS_BASE__MIN_MISCELLANY_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? N_("creating 'miscellaneous' table")
                            : N_("opening 'miscellaneous' table")),
                       svn_fs_bdb__open_miscellaneous_table(&bfd->miscellaneous,
                                                            bfd->bdb->env,
                                                            create)));
    }

  if (format >= SVN_FS_BASE__MIN_REP_SHARING_FORMAT)
    {
      SVN_ERR(BDB_WRAP(fs, (create
                            ? N_("creating 'checksum-reps' table")
                            : N_("opening 'checksum-reps' table")),
                       svn_fs_bdb__open_checksum_reps_table(&bfd->checksum_reps,
                                                            bfd->bdb->env,
                                                            create)));
    }

  return SVN_NO_ERROR;
}
Пример #28
0
static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex,
                                            const char *fname)
{
    #define APR_POSIXSEM_NAME_MIN 13
    sem_t *psem;
    char semname[32];
    
    new_mutex->interproc = apr_palloc(new_mutex->pool,
                                      sizeof(*new_mutex->interproc));
    /*
     * This bogusness is to follow what appears to be the
     * lowest common denominator in Posix semaphore naming:
     *   - start with '/'
     *   - be at most 14 chars
     *   - be unique and not match anything on the filesystem
     *
     * Because of this, we use fname to generate a (unique) hash
     * and use that as the name of the semaphore. If no filename was
     * given, we create one based on the time. We tuck the name
     * away, since it might be useful for debugging. We use 2 hashing
     * functions to try to avoid collisions.
     *
     * To  make this as robust as possible, we initially try something
     * larger (and hopefully more unique) and gracefully fail down to the
     * LCD above.
     *
     * NOTE: Darwin (Mac OS X) seems to be the most restrictive
     * implementation. Versions previous to Darwin 6.2 had the 14
     * char limit, but later rev's allow up to 31 characters.
     *
     */
    if (fname) {
        apr_ssize_t flen = strlen(fname);
        char *p = apr_pstrndup(new_mutex->pool, fname, strlen(fname));
        unsigned int h1, h2;
        h1 = (apr_hashfunc_default((const char *)p, &flen) & 0xffffffff);
        h2 = (rshash(p) & 0xffffffff);
        apr_snprintf(semname, sizeof(semname), "/ApR.%xH%x", h1, h2);
    } else {
        apr_time_t now;
        unsigned long sec;
        unsigned long usec;
        now = apr_time_now();
        sec = apr_time_sec(now);
        usec = apr_time_usec(now);
        apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec);
    }
    psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
    if (psem == (sem_t *)SEM_FAILED) {
        if (errno == ENAMETOOLONG) {
            /* Oh well, good try */
            semname[APR_POSIXSEM_NAME_MIN] = '\0';
        } else {
            return errno;
        }
        psem = sem_open(semname, O_CREAT | O_EXCL, 0644, 1);
    }

    if (psem == (sem_t *)SEM_FAILED) {
        return errno;
    }
    /* Ahhh. The joys of Posix sems. Predelete it... */
    sem_unlink(semname);
    new_mutex->psem_interproc = psem;
    new_mutex->fname = apr_pstrdup(new_mutex->pool, semname);
    apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex,
                              apr_proc_mutex_cleanup, 
                              apr_pool_cleanup_null);
    return APR_SUCCESS;
}
Пример #29
0
    mbox_cache_update(mbox_cache_info ** mlix,
                  const char *path, apr_pool_t *pool,
                  char *list, char *domain)
{
    apr_status_t rv;
    char *temp;
    apr_datum_t key;
    apr_datum_t nv;
    mbox_cache_info *mli;
    int update_only = 0;
    int tver;

    OPEN_DBM(pool, mli, APR_DBM_READWRITE, path, temp, rv);

    if (rv != APR_SUCCESS) {
        OPEN_DBM(pool, mli, APR_DBM_RWCREATE, path, temp, rv);

        mli->mtime = 0;
        if (rv != APR_SUCCESS) {
            return rv;
        }
    }
    else {
        update_only = 1;
    }

    mli->pool = pool;
    apr_pool_cleanup_register(pool, (void *) mli, mli_cleanup,
                              apr_pool_cleanup_null);

    key.dptr = str_cache_version;
    key.dsize = strlen(str_cache_version) + 1;
    tver = MBOX_CACHE_VERSION;

    temp = apr_palloc(pool, sizeof(tver));
    memcpy(temp, &tver, sizeof(tver));

    nv.dptr = temp;
    nv.dsize = sizeof(tver);
    rv = apr_dbm_store(mli->db, key, nv);

    if (rv != APR_SUCCESS) {
        return rv;
    }

    if (update_only == 1) {
        key.dptr = str_cache_mtime;
        key.dsize = strlen(str_cache_mtime) + 1;
        rv = apr_dbm_fetch(mli->db, key, &nv);

        if (rv != APR_SUCCESS) {
            apr_dbm_close(mli->db);
            return rv;
        }
        if (nv.dptr && nv.dsize == sizeof(mli->mtime)) {
            memcpy(&mli->mtime, nv.dptr, sizeof(mli->mtime));
        }
        else {
            mli->mtime = 0;
        }
    }
    else {
        mli->mtime = 0;
    }

    key.dptr = str_cache_list;
    key.dsize = strlen(str_cache_list) + 1;
    nv.dptr = list;
    nv.dsize = strlen(list) + 1;
    rv = apr_dbm_store(mli->db, key, nv);
    if (rv != APR_SUCCESS) {
        return rv;
    }
    mli->domain = apr_pstrdup(pool, list);

    key.dptr = str_cache_domain;
    key.dsize = strlen(str_cache_domain) + 1;
    nv.dptr = domain;
    nv.dsize = strlen(domain) + 1;
    rv = apr_dbm_store(mli->db, key, nv);

    if (rv != APR_SUCCESS) {
        return rv;
    }
    mli->domain = apr_pstrdup(pool, domain);

    *mlix = mli;

    return rv;
}
Пример #30
0
APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
                                                     apr_file_t **out,
                                                     apr_int32_t blocking,
                                                     apr_pool_t *pool_in,
                                                     apr_pool_t *pool_out)
{
#ifdef _WIN32_WCE
    return APR_ENOTIMPL;
#else
    SECURITY_ATTRIBUTES sa;
    static unsigned long id = 0;
    DWORD dwPipeMode;
    DWORD dwOpenMode;

    sa.nLength = sizeof(sa);

#if APR_HAS_UNICODE_FS
    IF_WIN_OS_IS_UNICODE
        sa.bInheritHandle = FALSE;
#endif
#if APR_HAS_ANSI_FS
    ELSE_WIN_OS_IS_ANSI
        sa.bInheritHandle = TRUE;
#endif
    sa.lpSecurityDescriptor = NULL;

    (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t));
    (*in)->pool = pool_in;
    (*in)->fname = NULL;
    (*in)->pipe = 1;
    (*in)->timeout = -1;
    (*in)->ungetchar = -1;
    (*in)->eof_hit = 0;
    (*in)->filePtr = 0;
    (*in)->bufpos = 0;
    (*in)->dataRead = 0;
    (*in)->direction = 0;
    (*in)->pOverlapped = NULL;
#if APR_FILES_AS_SOCKETS
    (void) apr_pollset_create(&(*in)->pollset, 1, p, 0);
#endif
    (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t));
    (*out)->pool = pool_out;
    (*out)->fname = NULL;
    (*out)->pipe = 1;
    (*out)->timeout = -1;
    (*out)->ungetchar = -1;
    (*out)->eof_hit = 0;
    (*out)->filePtr = 0;
    (*out)->bufpos = 0;
    (*out)->dataRead = 0;
    (*out)->direction = 0;
    (*out)->pOverlapped = NULL;
#if APR_FILES_AS_SOCKETS
    (void) apr_pollset_create(&(*out)->pollset, 1, p, 0);
#endif
    if (apr_os_level >= APR_WIN_NT) {
        char rand[8];
        int pid = getpid();
#define FMT_PIPE_NAME "\\\\.\\pipe\\apr-pipe-%x.%lx."
        /*                                    ^   ^ ^
         *                                  pid   | |
         *                                        | |
         *                                       id |
         *                                          |
         *                        hex-escaped rand[8] (16 bytes)
         */
        char name[sizeof FMT_PIPE_NAME + 2 * sizeof(pid)
                                       + 2 * sizeof(id)
                                       + 2 * sizeof(rand)];
        apr_size_t pos;

        /* Create the read end of the pipe */
        dwOpenMode = PIPE_ACCESS_INBOUND;
#ifdef FILE_FLAG_FIRST_PIPE_INSTANCE
        dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
#endif
        if (blocking == APR_WRITE_BLOCK /* READ_NONBLOCK */
               || blocking == APR_FULL_NONBLOCK) {
            dwOpenMode |= FILE_FLAG_OVERLAPPED;
            (*in)->pOverlapped =
                    (OVERLAPPED*) apr_pcalloc((*in)->pool, sizeof(OVERLAPPED));
            (*in)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            (*in)->timeout = 0;
        }
        dwPipeMode = 0;

        apr_generate_random_bytes(rand, sizeof rand);
        pos = apr_snprintf(name, sizeof name, FMT_PIPE_NAME, pid, id++);
        apr_escape_hex(name + pos, rand, sizeof rand, 0, NULL);

        (*in)->filehand = CreateNamedPipe(name,
                                          dwOpenMode,
                                          dwPipeMode,
                                          1,            /* nMaxInstances,   */
                                          0,            /* nOutBufferSize,  */
                                          65536,        /* nInBufferSize,   */
                                          1,            /* nDefaultTimeOut, */
                                          &sa);
        if ((*in)->filehand == INVALID_HANDLE_VALUE) {
            apr_status_t rv = apr_get_os_error();
            file_cleanup(*in);
            return rv;
        }

        /* Create the write end of the pipe */
        dwOpenMode = FILE_ATTRIBUTE_NORMAL;
        if (blocking == APR_READ_BLOCK /* WRITE_NONBLOCK */
                || blocking == APR_FULL_NONBLOCK) {
            dwOpenMode |= FILE_FLAG_OVERLAPPED;
            (*out)->pOverlapped =
                    (OVERLAPPED*) apr_pcalloc((*out)->pool, sizeof(OVERLAPPED));
            (*out)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            (*out)->timeout = 0;
        }

        (*out)->filehand = CreateFile(name,
                                      GENERIC_WRITE,   /* access mode             */
                                      0,               /* share mode              */
                                      &sa,             /* Security attributes     */
                                      OPEN_EXISTING,   /* dwCreationDisposition   */
                                      dwOpenMode,      /* Pipe attributes         */
                                      NULL);           /* handle to template file */
        if ((*out)->filehand == INVALID_HANDLE_VALUE) {
            apr_status_t rv = apr_get_os_error();
            file_cleanup(*out);
            file_cleanup(*in);
            return rv;
        }
    }
    else {
        /* Pipes on Win9* are blocking. Live with it. */
        if (!CreatePipe(&(*in)->filehand, &(*out)->filehand, &sa, 65536)) {
            return apr_get_os_error();
        }
    }

    apr_pool_cleanup_register((*in)->pool, (void *)(*in), file_cleanup,
                        apr_pool_cleanup_null);
    apr_pool_cleanup_register((*out)->pool, (void *)(*out), file_cleanup,
                        apr_pool_cleanup_null);
    return APR_SUCCESS;
#endif /* _WIN32_WCE */
}