Exemple #1
0
/* this has to be the first function called by a new thread */
TLS_DATA *tls_alloc(CLI *c, TLS_DATA *inherited, char *txt) {
    TLS_DATA *tls_data;

    if(inherited) { /* reuse the thread-local storage after fork() */
        tls_data=inherited;
        str_free(tls_data->id);
    } else {
        tls_data=calloc(1, sizeof(TLS_DATA));
        if(!tls_data)
            fatal("Out of memory");
        if(c)
            c->tls=tls_data;
        str_init(tls_data);
        tls_data->c=c;
        tls_data->opt=c?c->opt:&service_options;
    }
    tls_data->id="unconfigured";
    tls_set(tls_data);

    /* str.c functions can be used below this point */
    if(txt) {
        tls_data->id=str_dup(txt);
        str_detach(tls_data->id); /* it is deallocated after str_stats() */
    } else if(c) {
        tls_data->id=log_id(c);
        str_detach(tls_data->id); /* it is deallocated after str_stats() */
    }

    return tls_data;
}
Exemple #2
0
static CONTEXT *new_context(void) {
    static int next_id=1;
    CONTEXT *context;

    /* allocate and fill the CONTEXT structure */
    context=str_alloc(sizeof(CONTEXT));
    if(!context) {
        s_log(LOG_ERR, "Unable to allocate CONTEXT structure");
        return NULL;
    }
    str_detach(context);
    context->id=next_id++;
    context->fds=NULL;
    context->ready=0;

    /* append to the tail of the ready queue */
    context->next=NULL;
    if(ready_tail)
        ready_tail->next=context;
    ready_tail=context;
    if(!ready_head)
        ready_head=context;

    return context;
}
Exemple #3
0
/* allocate local data structure for the new thread */
CLI *alloc_client_session(SERVICE_OPTIONS *opt, int rfd, int wfd) {
    CLI *c;

    c=str_alloc(sizeof(CLI));
    str_detach(c);
    c->opt=opt;
    c->local_rfd.fd=rfd;
    c->local_wfd.fd=wfd;
    return c;
}
Exemple #4
0
static struct CRYPTO_dynlock_value *dyn_create_function(const char *file,
        int line) {
    struct CRYPTO_dynlock_value *value;

    (void)file; /* skip warning about unused parameter */
    (void)line; /* skip warning about unused parameter */
    value=str_alloc(sizeof(struct CRYPTO_dynlock_value));
    if(!value)
        return NULL;
    str_detach(value);
    InitializeCriticalSection(&value->mutex);
    return value;
}
Exemple #5
0
int create_client(int ls, int s, CLI *arg, void *(*cli)(void *)) {
    CONTEXT *context;

    (void)ls; /* this parameter is only used with USE_FORK */
    
    s_log(LOG_DEBUG, "Creating a new context");
    context=new_context();
    if(!context) {
        if(arg)
            str_free(arg);
        if(s>=0)
            closesocket(s);
        return -1;
    }

    /* initialize context_t structure */
    if(getcontext(&context->context)<0) {
        str_free(context);
        if(arg)
            str_free(arg);
        if(s>=0)
            closesocket(s);
        ioerror("getcontext");
        return -1;
    }
    context->context.uc_link=NULL; /* stunnel does not use uc_link */

    /* create stack */
    context->stack=str_alloc(arg->opt->stack_size);
    if(!context->stack) {
        str_free(context);
        if(arg)
            str_free(arg);
        if(s>=0)
            closesocket(s);
        s_log(LOG_ERR, "Unable to allocate stack");
        return -1;
    }
    str_detach(context->stack);
#if defined(__sgi) || ARGC==2 /* obsolete ss_sp semantics */
    context->context.uc_stack.ss_sp=context->stack+arg->opt->stack_size-8;
#else
    context->context.uc_stack.ss_sp=context->stack;
#endif
    context->context.uc_stack.ss_size=arg->opt->stack_size;
    context->context.uc_stack.ss_flags=0;

    makecontext(&context->context, (void(*)(void))cli, ARGC, arg);
    s_log(LOG_DEBUG, "New context created");
    return 0;
}
Exemple #6
0
static void win_new_chain(CLI *c) {
    BIO *bio;
    int i, len;
    X509 *peer=NULL;
    STACK_OF(X509) *sk;
    char *chain;

    if(c->opt->chain) /* already cached */
        return; /* this race condition is safe to ignore */
    bio=BIO_new(BIO_s_mem());
    if(!bio)
        return;
    sk=SSL_get_peer_cert_chain(c->ssl);
    for(i=0; sk && i<sk_X509_num(sk); i++) {
        peer=sk_X509_value(sk, i);
        PEM_write_bio_X509(bio, peer);
    }
    if(!sk || !c->opt->option.client) {
        peer=SSL_get_peer_certificate(c->ssl);
        if(peer) {
            PEM_write_bio_X509(bio, peer);
            X509_free(peer);
        }
    }
    len=BIO_pending(bio);
    if(len<=0) {
        s_log(LOG_INFO, "No peer certificate received");
        BIO_free(bio);
        return;
    }
    chain=str_alloc(len+1);
    len=BIO_read(bio, chain, len);
    if(len<0) {
        s_log(LOG_ERR, "BIO_read failed");
        BIO_free(bio);
        str_free(chain);
        return;
    }
    chain[len]='\0';
    BIO_free(bio);
    str_detach(chain); /* to prevent automatic deallocation of cached value */
    c->opt->chain=chain; /* this race condition is safe to ignore */
    PostMessage(hwnd, WM_NEW_CHAIN, c->opt->section_number, 0);
    s_log(LOG_DEBUG, "Peer certificate was cached (%d bytes)", len);
}
Exemple #7
0
void s_log(int level, const char *format, ...) {
    va_list ap;
    char *text, *stamp, *id;
    struct LIST *tmp;
#ifdef USE_WIN32
    DWORD libc_error;
#else
    int libc_error;
#endif
    int socket_error;
    time_t gmt;
    struct tm *timeptr;
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
    struct tm timestruct;
#endif
    TLS_DATA *tls_data;

    tls_data=tls_get();
    if(!tls_data) {
        tls_data=tls_alloc(NULL, NULL, "log");
        s_log(LOG_ERR, "INTERNAL ERROR: Uninitialized TLS at %s, line %d",
            __FILE__, __LINE__);
    }

    /* performance optimization: skip the trivial case early */
    if(log_mode==LOG_MODE_CONFIGURED && level>tls_data->opt->log_level)
        return;

    libc_error=get_last_error();
    socket_error=get_last_socket_error();

    /* format the id to be logged */
    time(&gmt);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
    timeptr=localtime_r(&gmt, &timestruct);
#else
    timeptr=localtime(&gmt);
#endif
    stamp=str_printf("%04d.%02d.%02d %02d:%02d:%02d",
        timeptr->tm_year+1900, timeptr->tm_mon+1, timeptr->tm_mday,
        timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
    id=str_printf("LOG%d[%s]", level, tls_data->id);

    /* format the text to be logged */
    va_start(ap, format);
    text=str_vprintf(format, ap);
    va_end(ap);
    safestring(text);

    CRYPTO_THREAD_read_lock(stunnel_locks[LOCK_LOG_MODE]);
    if(log_mode==LOG_MODE_BUFFER) { /* save the text to log it later */
        CRYPTO_THREAD_write_lock(stunnel_locks[LOCK_LOG_BUFFER]);
        tmp=str_alloc_detached(sizeof(struct LIST));
        tmp->next=NULL;
        tmp->opt=tls_data->opt;
        tmp->level=level;
        tmp->stamp=stamp;
        str_detach(tmp->stamp);
        tmp->id=id;
        str_detach(tmp->id);
        tmp->text=text;
        str_detach(tmp->text);
        if(tail)
            tail->next=tmp;
        else
            head=tmp;
        tail=tmp;
        CRYPTO_THREAD_write_unlock(stunnel_locks[LOCK_LOG_BUFFER]);
    } else { /* ready log the text directly */
        log_raw(tls_data->opt, level, stamp, id, text);
        str_free(stamp);
        str_free(id);
        str_free(text);
    }
    CRYPTO_THREAD_read_unlock(stunnel_locks[LOCK_LOG_MODE]);

    set_last_error(libc_error);
    set_last_socket_error(socket_error);
}
Exemple #8
0
void ui_new_log(const char *line) {
    LPTSTR txt;
    txt=str2tstr(line);
    str_detach(txt); /* this allocation will be freed in the GUI thread */
    PostMessage(hwnd, WM_LOG, (WPARAM)txt, 0);
}