Esempio n. 1
0
File: gui.c Progetto: djs55/stunnel
static int service_install(LPSTR command_line) {
    SC_HANDLE scm, service;
    char exe_file_name[STRLEN], service_path[STRLEN];

    scm=OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
    if(!scm) {
        error_box(TEXT("OpenSCManager"));
        return 1;
    }
    GetModuleFileName(0, exe_file_name, STRLEN);
    safecopy(service_path, "\"");
    safeconcat(service_path, exe_file_name);
    safeconcat(service_path, "\" -service ");
    safeconcat(service_path, command_line);
    service=CreateService(scm,
        options.win32_service, options.win32_service, SERVICE_ALL_ACCESS,
        SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
        SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, service_path,
        NULL, NULL, NULL, NULL, NULL);
    if(!service) {
        error_box(TEXT("CreateService"));
        CloseServiceHandle(scm);
        return 1;
    }
    if(!cmdline.quiet)
        MessageBox(hwnd, TEXT("Service installed"),
            win32_name, MB_ICONINFORMATION);
    CloseServiceHandle(service);
    CloseServiceHandle(scm);
    return 0;
}
Esempio n. 2
0
static void print_option(char *line, int type, OPT_UNION *val) {
    char text[STRLEN];

    if(!val) {
        safecopy(text, "    --    ");
    } else {
        switch(type) {
        case TYPE_FLAG:
        case TYPE_INT:
            sprintf(text, "%10d", val->i_val);
            break;
        case TYPE_LINGER:
            sprintf(text, "%d:%-8d",
                val->linger_val.l_onoff, val->linger_val.l_linger);
            break;
        case TYPE_TIMEVAL:
            sprintf(text, "%6d:%-3d",
                (int)val->timeval_val.tv_sec, (int)val->timeval_val.tv_usec);
            break;
        case TYPE_STRING:
            sprintf(text, "%10s", val->c_val);
            break;
        default:
            safecopy(text, "  Ooops?  "); /* Internal error? */
        }
    }
    safeconcat(line, text);
}
Esempio n. 3
0
static int print_socket_options(void) {
    int fd, len;
    SOCK_OPT *ptr;
    OPT_UNION val;
    char line[STRLEN];

    fd=socket(AF_INET, SOCK_STREAM, 0);

    log_raw("Socket option defaults:");
    log_raw("    %-16s%-10s%-10s%-10s%-10s",
        "Option", "Accept", "Local", "Remote", "OS default");
    for(ptr=sock_opts; ptr->opt_str; ptr++) {
        /* display option name */
        sprintf(line, "    %-16s", ptr->opt_str);
        /* display stunnel default values */
        print_option(line, ptr->opt_type, ptr->opt_val[0]);
        print_option(line, ptr->opt_type, ptr->opt_val[1]);
        print_option(line, ptr->opt_type, ptr->opt_val[2]);
        /* display OS default value */
        len = sizeof(val);
        if(getsockopt(fd, ptr->opt_level, ptr->opt_name, (void *)&val, &len)) {
            if(get_last_socket_error()!=ENOPROTOOPT) {
                log_raw("%s", line); /* dump the name and assigned values */
                sockerror("getsockopt");
                return 0; /* FAILED */
            }
            safeconcat(line, "    --    "); /* write-only value */
        } else
            print_option(line, ptr->opt_type, &val);
        log_raw("%s", line);
    }
    return 1; /* OK */
}
Esempio n. 4
0
static LRESULT CALLBACK pass_proc(HWND hDlg, UINT message,
        WPARAM wParam, LPARAM lParam) {
    char titlebar[STRLEN];
    WORD cchPassword;

    switch (message) {
    case WM_INITDIALOG:
        /* Set the default push button to "Cancel." */
        SendMessage(hDlg, DM_SETDEFID, (WPARAM) IDCANCEL, (LPARAM) 0);

        safecopy(titlebar, "Private key: ");
        safeconcat(titlebar, "options.key");
        SetWindowText(hDlg, titlebar);
		win_log("init");
        return TRUE;

    case WM_COMMAND:
        /* Set the default push button to "OK" when the user enters text. */
        if(HIWORD (wParam) == EN_CHANGE && LOWORD(wParam) == IDE_PASSWORDEDIT)
            SendMessage(hDlg, DM_SETDEFID, (WPARAM) IDOK, (LPARAM) 0);
        switch(wParam) {
        case IDOK:
            /* Get number of characters. */
            cchPassword = (WORD) SendDlgItemMessage(hDlg,
                IDE_PASSWORDEDIT, EM_LINELENGTH, (WPARAM) 0, (LPARAM) 0);
            if(cchPassword==0 || cchPassword>=STRLEN) {
                EndDialog(hDlg, FALSE);
                return FALSE;
            }

            /* Put the number of characters into first word of buffer. */
            *((LPWORD)passphrase) = cchPassword;

            /* Get the characters. */
            SendDlgItemMessage(hDlg, IDE_PASSWORDEDIT, EM_GETLINE,
                (WPARAM) 0, /* line 0 */ (LPARAM) passphrase);

            passphrase[cchPassword] = 0; /* Null-terminate the string. */
            EndDialog(hDlg, TRUE);
            return TRUE;

        case IDCANCEL:
            EndDialog(hDlg, FALSE);
            return TRUE;
        }
        return 0;
    }
    return FALSE;

    UNREFERENCED_PARAMETER(lParam);
}
Esempio n. 5
0
File: gui.c Progetto: djs55/stunnel
static int set_cwd(void) {
    char *c, errmsg[STRLEN], exe_file_name[STRLEN];

    GetModuleFileName(0, exe_file_name, STRLEN);
    c=strrchr(exe_file_name, '\\'); /* last backslash */
    if(c) /* found */
        c[1]='\0'; /* truncate program name */
    if(!SetCurrentDirectory(exe_file_name)) {
        safecopy(errmsg, "Cannot set directory to ");
        safeconcat(errmsg, exe_file_name);
        MessageBox(hwnd, errmsg, TEXT("stunnel"), MB_ICONERROR);
        return 1;
    }
    return 0;
}
Esempio n. 6
0
void fdputline(CLI *c, int fd, char *line) {
    char tmpline[STRLEN];
    const char crlf[]="\r\n";
    int len;

    if(strlen(line)+2>=STRLEN) { /* 2 for crlf */
        s_log(LOG_ERR, "Line too long in fdputline");
        longjmp(c->err, 1);
    }
    safecopy(tmpline, line);
    safeconcat(tmpline, crlf);
    len=strlen(tmpline);
    write_blocking(c, fd, tmpline, len);
    tmpline[len-2]='\0'; /* remove CRLF */
    safestring(tmpline);
    s_log(LOG_DEBUG, " -> %s", tmpline);
}
Esempio n. 7
0
static int connect_local(CLI *c) { /* spawn local process */
#if defined (USE_WIN32) || defined (__vms)
    s_log(LOG_ERR, "LOCAL MODE NOT SUPPORTED ON WIN32 and OpenVMS PLATFORM");
    return -1;
#else /* USE_WIN32, __vms */
    char env[3][STRLEN], name[STRLEN], *portname;
    int fd[2], pid;
    X509 *peer;
#ifdef HAVE_PTHREAD_SIGMASK
    sigset_t newmask;
#endif

    if (c->opt->option.pty) {
        char tty[STRLEN];

        if(pty_allocate(fd, fd+1, tty, STRLEN)) {
            return -1;
        }
        s_log(LOG_DEBUG, "%s allocated", tty);
    } else {
        if(make_sockets(fd))
            return -1;
    }
    pid=fork();
    c->pid=(unsigned long)pid;
    switch(pid) {
    case -1:    /* error */
        closesocket(fd[0]);
        closesocket(fd[1]);
        ioerror("fork");
        return -1;
    case  0:    /* child */
        closesocket(fd[0]);
        dup2(fd[1], 0);
        dup2(fd[1], 1);
        if(!options.option.foreground)
            dup2(fd[1], 2);
        closesocket(fd[1]);
        safecopy(env[0], "REMOTE_HOST=");
        safeconcat(env[0], c->accepting_address);
        portname=strrchr(env[0], ':');
        if(portname) /* strip the port name */
            *portname='\0';
        putenv(env[0]);
        if(c->opt->option.transparent) {
            putenv("LD_PRELOAD=" LIBDIR "/libstunnel.so");
            /* For Tru64 _RLD_LIST is used instead */
            putenv("_RLD_LIST=" LIBDIR "/libstunnel.so:DEFAULT");
        }
        if(c->ssl) {
            peer=SSL_get_peer_certificate(c->ssl);
            if(peer) {
                safecopy(env[1], "SSL_CLIENT_DN=");
                X509_NAME_oneline(X509_get_subject_name(peer), name, STRLEN);
                safestring(name);
                safeconcat(env[1], name);
                putenv(env[1]);
                safecopy(env[2], "SSL_CLIENT_I_DN=");
                X509_NAME_oneline(X509_get_issuer_name(peer), name, STRLEN);
                safestring(name);
                safeconcat(env[2], name);
                putenv(env[2]);
                X509_free(peer);
            }
        }
#ifdef HAVE_PTHREAD_SIGMASK
        sigemptyset(&newmask);
        sigprocmask(SIG_SETMASK, &newmask, NULL);
#endif
        execvp(c->opt->execname, c->opt->execargs);
        ioerror(c->opt->execname); /* execv failed */
        _exit(1);
    default:
        break;
    }
    /* parent */
    s_log(LOG_INFO, "Local mode child started (PID=%lu)", c->pid);
    closesocket(fd[1]);
#ifdef FD_CLOEXEC
    fcntl(fd[0], F_SETFD, FD_CLOEXEC);
#endif
    return fd[0];
#endif /* USE_WIN32,__vms */
}
Esempio n. 8
0
char *stunnel_info(void) {
    static char retval[STRLEN];

    safecopy(retval, "stunnel " VERSION " on " HOST);
#ifdef USE_UCONTEXT
    safeconcat(retval, " UCONTEXT");
#endif
#ifdef USE_PTHREAD
    safeconcat(retval, " PTHREAD");
#endif
#ifdef USE_WIN32
    safeconcat(retval, " WIN32");
#endif
#ifdef USE_FORK
    safeconcat(retval, " FORK");
#endif
#ifdef USE_POLL
    safeconcat(retval, "+POLL");
#else /* defined(USE_POLL) */
    safeconcat(retval, "+SELECT");
#endif /* defined(USE_POLL) */
#ifdef USE_WIN32
    if(s_getaddrinfo)
        safeconcat(retval, "+IPv6");
    else
        safeconcat(retval, "+IPv4");
#else /* defined(USE_WIN32) */
#if defined(USE_IPv6)
    safeconcat(retval, "+IPv6");
#else /* defined(USE_IPv6) */
    safeconcat(retval, "+IPv4");
#endif /* defined(USE_IPv6) */
#endif /* defined(USE_WIN32) */
#ifdef USE_LIBWRAP
    safeconcat(retval, "+LIBWRAP");
#endif
    safeconcat(retval, " with ");
    safeconcat(retval, SSLeay_version(SSLEAY_VERSION));
    return retval;
}
Esempio n. 9
0
static char *global_options(CMD cmd, char *opt, char *arg) {

    if(cmd==CMD_DEFAULT || cmd==CMD_HELP) {
        log_raw("Global options");
    }

    /* CApath */
    switch(cmd) {
    case CMD_INIT:
#if 0
        options.ca_dir=(char *)X509_get_default_cert_dir();
#endif
        options.ca_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CApath"))
            break;
        if(arg[0]) /* not empty */
            options.ca_dir=stralloc(arg);
        else
            options.ca_dir=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
#if 0
        log_raw("%-15s = %s", "CApath",
            options.ca_dir ? options.ca_dir : "(none)");
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = CA certificate directory for 'verify' option",
            "CApath");
        break;
    }

    /* CAfile */
    switch(cmd) {
    case CMD_INIT:
#if 0
        options.ca_file=(char *)X509_get_default_certfile();
#endif
        options.ca_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CAfile"))
            break;
        if(arg[0]) /* not empty */
            options.ca_file=stralloc(arg);
        else
            options.ca_file=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
#if 0
        log_raw("%-15s = %s", "CAfile",
            options.ca_file ? options.ca_file : "(none)");
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = CA certificate file for 'verify' option",
            "CAfile");
        break;
    }

    /* cert */
    switch(cmd) {
    case CMD_INIT:
#ifdef CONFDIR
        options.cert=CONFDIR "/stunnel.pem";
#else
        options.cert="stunnel.pem";
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "cert"))
            break;
        options.cert=stralloc(arg);
        options.option.cert=1;
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "cert", options.cert);
        break;
    case CMD_HELP:
        log_raw("%-15s = certificate chain", "cert");
        break;
    }

    /* chroot */
#ifdef HAVE_CHROOT
    switch(cmd) {
    case CMD_INIT:
        options.chroot_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "chroot"))
            break;
        options.chroot_dir=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = directory to chroot stunnel process", "chroot");
        break;
    }
#endif /* HAVE_CHROOT */

    /* ciphers */
    switch(cmd) {
    case CMD_INIT:
        options.cipher_list=SSL_DEFAULT_CIPHER_LIST;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "ciphers"))
            break;
        options.cipher_list=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "ciphers", SSL_DEFAULT_CIPHER_LIST);
        break;
    case CMD_HELP:
        log_raw("%-15s = list of permitted SSL ciphers", "ciphers");
        break;
    }

    /* client */
    switch(cmd) {
    case CMD_INIT:
        options.option.client=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "client"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.client=1;
        else if(!strcasecmp(arg, "no"))
            options.option.client=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no client mode (remote service uses SSL)",
            "client");
        break;
    }

    /* CRLpath */
    switch(cmd) {
    case CMD_INIT:
        options.crl_dir=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CRLpath"))
            break;
        if(arg[0]) /* not empty */
            options.crl_dir=stralloc(arg);
        else
            options.crl_dir=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = CRL directory", "CRLpath");
        break;
    }

    /* CRLfile */
    switch(cmd) {
    case CMD_INIT:
        options.crl_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "CRLfile"))
            break;
        if(arg[0]) /* not empty */
            options.crl_file=stralloc(arg);
        else
            options.crl_file=NULL;
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = CRL file", "CRLfile");
        break;
    }

    /* debug */
    switch(cmd) {
    case CMD_INIT:
        options.debug_level=5;
#if !defined (USE_WIN32) && !defined (__vms)
        options.facility=LOG_DAEMON;
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "debug"))
            break;
        if(!parse_debug_level(arg))
            return "Illegal debug argument";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %d", "debug", options.debug_level);
        break;
    case CMD_HELP:
        log_raw("%-15s = [facility].level (e.g. daemon.info)", "debug");
        break;
    }

    /* EGD is only supported when compiled with OpenSSL 0.9.5a or later */
#if SSLEAY_VERSION_NUMBER >= 0x0090581fL
    switch(cmd) {
    case CMD_INIT:
        options.egd_sock=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "EGD"))
            break;
        options.egd_sock=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef EGD_SOCKET
        log_raw("%-15s = %s", "EGD", EGD_SOCKET);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = path to Entropy Gathering Daemon socket", "EGD");
        break;
    }
#endif /* OpenSSL 0.9.5a */

    /* foreground */
#ifndef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.option.syslog=0;
        options.option.foreground=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "foreground"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.foreground=1;
        else if(!strcasecmp(arg, "no"))
            options.option.foreground=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no foreground mode (don't fork, log to stderr)",
            "foreground");
        break;
    }
#endif

    /* key */
    switch(cmd) {
    case CMD_INIT:
        options.key=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "key"))
            break;
        options.key=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "key", options.cert); /* set in stunnel.c */
        break;
    case CMD_HELP:
        log_raw("%-15s = certificate private key", "key");
        break;
    }

    /* options */
    switch(cmd) {
    case CMD_INIT:
        options.ssl_options=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "options"))
            break;
        if(!parse_ssl_option(arg))
            return "Illegal SSL option";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = SSL option", "options");
        log_raw("%18sset an SSL option", "");
        break;
    }

    /* output */
    switch(cmd) {
    case CMD_INIT:
        options.output_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "output"))
            break;
        options.output_file=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = file to append log messages", "output");
        break;
    }

    /* pid */
#ifndef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.pidfile=PIDFILE;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "pid"))
            break;
        if(arg[0]) /* is argument not empty? */
            options.pidfile=stralloc(arg);
        else
            options.pidfile=NULL; /* empty -> do not create a pid file */
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %s", "pid", PIDFILE);
        break;
    case CMD_HELP:
        log_raw("%-15s = pid file (empty to disable creating)", "pid");
        break;
    }
#endif

    /* RNDbytes */
    switch(cmd) {
    case CMD_INIT:
        options.random_bytes=RANDOM_BYTES;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDbytes"))
            break;
        options.random_bytes=atoi(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %d", "RNDbytes", RANDOM_BYTES);
        break;
    case CMD_HELP:
        log_raw("%-15s = bytes to read from random seed files", "RNDbytes");
        break;
    }

    /* RNDfile */
    switch(cmd) {
    case CMD_INIT:
        options.rand_file=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDfile"))
            break;
        options.rand_file=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef RANDOM_FILE
        log_raw("%-15s = %s", "RNDfile", RANDOM_FILE);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = path to file with random seed data", "RNDfile");
        break;
    }

    /* RNDoverwrite */
    switch(cmd) {
    case CMD_INIT:
        options.option.rand_write=1;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "RNDoverwrite"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.rand_write=1;
        else if(!strcasecmp(arg, "no"))
            options.option.rand_write=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = yes", "RNDoverwrite");
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no overwrite seed datafiles with new random data",
            "RNDoverwrite");
        break;
    }

    /* service */
    switch(cmd) {
    case CMD_INIT:
        local_options.servname=stralloc("stunnel");
#ifdef USE_WIN32
        options.win32_service="stunnel";
        options.win32_name="stunnel " VERSION " on Win32";
#endif
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "service"))
            break;
        local_options.servname=stralloc(arg);
#ifdef USE_WIN32
        options.win32_service=stralloc(arg);
        {
            char tmpstr[STRLEN];

            safecopy(tmpstr, "stunnel " VERSION " on Win32 (");
            safeconcat(tmpstr, arg);
            safeconcat(tmpstr, ")");
            options.win32_name=stralloc(tmpstr);
        }
#endif
        return NULL; /* OK */
    case CMD_DEFAULT:
#ifdef USE_WIN32
        log_raw("%-15s = %s", "service", options.win32_service);
#endif
        break;
    case CMD_HELP:
        log_raw("%-15s = service name", "service");
        break;
    }

    /* session */
    switch(cmd) {
    case CMD_INIT:
        options.session_timeout=300;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "session"))
            break;
        if(atoi(arg)>0)
            options.session_timeout=atoi(arg);
        else
            return "Illegal session timeout";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = %ld seconds", "session", options.session_timeout);
        break;
    case CMD_HELP:
        log_raw("%-15s = session cache timeout (in seconds)", "session");
        break;
    }

#ifndef USE_WIN32
    /* setgid */
    switch(cmd) {
    case CMD_INIT:
        options.setgid_group=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "setgid"))
            break;
        options.setgid_group=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = groupname for setgid()", "setgid");
        break;
    }
#endif

#ifndef USE_WIN32
    /* setuid */
    switch(cmd) {
    case CMD_INIT:
        options.setuid_user=NULL;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "setuid"))
            break;
        options.setuid_user=stralloc(arg);
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = username for setuid()", "setuid");
        break;
    }
#endif

    /* socket */
    switch(cmd) {
    case CMD_INIT:
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "socket"))
            break;
        if(!parse_socket_option(arg))
            return "Illegal socket option";
        return NULL; /* OK */
    case CMD_DEFAULT:
        break;
    case CMD_HELP:
        log_raw("%-15s = a|l|r:option=value[:value]", "socket");
        log_raw("%18sset an option on accept/local/remote socket", "");
        break;
    }

    /* taskbar */
#ifdef USE_WIN32
    switch(cmd) {
    case CMD_INIT:
        options.option.taskbar=1;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "taskbar"))
            break;
        if(!strcasecmp(arg, "yes"))
            options.option.taskbar=1;
        else if(!strcasecmp(arg, "no"))
            options.option.taskbar=0;
        else
            return "argument should be either 'yes' or 'no'";
        return NULL; /* OK */
    case CMD_DEFAULT:
        log_raw("%-15s = yes", "taskbar");
        break;
    case CMD_HELP:
        log_raw("%-15s = yes|no enable the taskbar icon", "taskbar");
        break;
    }
#endif

    /* verify */
    switch(cmd) {
    case CMD_INIT:
        options.verify_level=-1;
        options.verify_use_only_my=0;
        break;
    case CMD_EXEC:
        if(strcasecmp(opt, "verify"))
            break;
        options.verify_level=SSL_VERIFY_NONE;
        switch(atoi(arg)) {
        case 3:
            options.verify_use_only_my=1;
        case 2:
            options.verify_level|=SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
        case 1:
            options.verify_level|=SSL_VERIFY_PEER;
        case 0:
            return NULL; /* OK */
        default:
            return "Bad verify level";
        }
    case CMD_DEFAULT:
        log_raw("%-15s = none", "verify");
        break;
    case CMD_HELP:
        log_raw("%-15s = level of peer certificate verification", "verify");
        log_raw("%18slevel 1 - verify peer certificate if present", "");
        log_raw("%18slevel 2 - require valid peer certificate always", "");
        log_raw("%18slevel 3 - verify peer with locally installed certificate",
        "");
        break;
    }

    if(cmd==CMD_EXEC)
        return option_not_found;
    return NULL; /* OK */
}