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; }
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); }
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 */ }
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); }
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; }
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); }
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 */ }
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; }
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 */ }