00001 #include "wvautoconf.h"
00002 #ifdef HAVE_UNISTD_H
00003 # include <unistd.h>
00004 #endif
00005 #ifdef HAVE_GETOPT_H
00006 # include <getopt.h>
00007 #endif
00008
00009 #ifndef _WIN32
00010 #include <signal.h>
00011 #include <sys/types.h>
00012 #include <sys/stat.h>
00013 #endif
00014
00015 #ifdef WITH_SLP
00016 #include "wvslp.h"
00017 #endif
00018
00019 #include "wvlogrcv.h"
00020 #include "uniconfdaemon.h"
00021 #include "uniclientconn.h"
00022 #include "unisecuregen.h"
00023 #include "unipermgen.h"
00024 #include "wvx509.h"
00025 #include "uniconfroot.h"
00026 #include "wvstrutils.h"
00027 #include "wvfileutils.h"
00028 #include "wvstreamsdaemon.h"
00029
00030 #ifdef WITH_SLP
00031 #include "slp.h"
00032 #endif
00033
00034 #ifdef _WIN32
00035 #pragma comment(linker, "/include:?UniRegistryGenMoniker@@3V?$WvMoniker@VIUniConfGen@@@@A")
00036 #pragma comment(linker, "/include:?UniPStoreGenMoniker@@3V?$WvMoniker@VIUniConfGen@@@@A")
00037 #pragma comment(linker, "/include:?UniIniGenMoniker@@3V?$WvMoniker@VIUniConfGen@@@@A")
00038 #endif
00039
00040 #define DEFAULT_CONFIG_FILE "ini:uniconf.ini"
00041
00042
00043 static WvMap<WvString, IUniConfGen*> namedgens(42);
00044
00045
00046 static IUniConfGen *creator(WvStringParm s)
00047 {
00048 IUniConfGen* gen = namedgens[s];
00049
00050 if (gen)
00051 gen->addRef();
00052
00053 return gen;
00054 }
00055
00056 WvMoniker<IUniConfGen> UniNamedMoniker("named", creator);
00057
00058
00059 class UniConfd : public WvStreamsDaemon
00060 {
00061 bool needauth;
00062 int port;
00063 int sslport;
00064 WvString unixport, permmon, unix_mode;
00065 time_t commit_interval;
00066
00067 UniConfRoot cfg;
00068 bool first_time;
00069 IUniConfGen *permgen;
00070
00071 bool namedgen_cb(WvStringParm option, void *)
00072 {
00073 WvString name(option);
00074 WvString moniker;
00075 char* ptr;
00076
00077 ptr = strchr(name.edit(), '=');
00078
00079 if (!ptr)
00080 return false;
00081
00082 *ptr = 0;
00083 moniker = ptr + 1;
00084
00085 namedgens.add(name, wvcreate<IUniConfGen>("temp:"), true);
00086 return true;
00087 }
00088
00089 void commit_stream_cb(WvStream &s, void *)
00090 {
00091 cfg.commit();
00092 cfg.refresh();
00093 if (permgen)
00094 permgen->refresh();
00095
00096 s.alarm(commit_interval * 1000);
00097 }
00098
00099 void startup(WvStreamsDaemon &, void *)
00100 {
00101 if (first_time)
00102 {
00103 WvStringList::Iter i(_extra_args);
00104 for (i.rewind(); i.next(); )
00105 {
00106 WvString path = *i, moniker;
00107 char *cptr = strchr(path.edit(), '=');
00108 if (!cptr)
00109 {
00110 moniker = path;
00111 path = "/";
00112 }
00113 else
00114 {
00115 *cptr = 0;
00116 moniker = cptr+1;
00117 }
00118
00119 log("Mounting '%s' on '%s': ", moniker, path);
00120 IUniConfGen *gen = cfg[path].mount(moniker, false);
00121 if (gen && gen->isok())
00122 log("ok.\n");
00123 else
00124 log("FAILED!\n");
00125 }
00126
00127 cfg.refresh();
00128 }
00129
00130 permgen = !!permmon ? wvcreate<IUniConfGen>(permmon) : NULL;
00131
00132 UniConfDaemon *daemon = new UniConfDaemon(cfg, needauth, permgen);
00133 add_die_stream(daemon, true, "uniconfd");
00134
00135 #ifndef _WIN32
00136 if (!!unixport)
00137 {
00138
00139 mkdirp(getdirname(unixport));
00140 ::unlink(unixport);
00141 if (!daemon->setupunixsocket(unixport))
00142 exit(3);
00143 if (!!unix_mode && unix_mode.num())
00144 {
00145 log("Setting mode on %s to: %s\n", unixport, unix_mode);
00146 mode_t mode;
00147 sscanf(unix_mode.edit(), "%o", &mode);
00148 chmod(unixport, mode);
00149 }
00150 }
00151 #endif
00152
00153 if (port && !daemon->setuptcpsocket(WvIPPortAddr("0.0.0.0", port)))
00154 {
00155 die();
00156 return;
00157 }
00158
00159 if (sslport)
00160 {
00161 WvString dName = encode_hostname_as_DN(fqdomainname());
00162 WvX509Mgr *x509cert = new WvX509Mgr(dName, 1024);
00163 if (!x509cert->isok())
00164 {
00165 log(WvLog::Critical,
00166 "Couldn't generate X509 certificate: SSL not available.\n");
00167 die();
00168 return;
00169 }
00170 else if (!daemon->setupsslsocket(
00171 WvIPPortAddr("0.0.0.0", sslport), x509cert))
00172 {
00173 die();
00174 return;
00175 }
00176 }
00177
00178 #ifdef WITH_SLP
00179 WvSlp slp;
00180
00181 if (first_time)
00182 {
00183
00184
00185
00186 if (port)
00187 slp.add_service("uniconf.niti", fqdomainname(), port);
00188
00189
00190 if (sslport)
00191 slp.add_service("uniconfs.niti", fqdomainname(), sslport);
00192 }
00193 #endif
00194
00195 WvStream *commit_stream = new WvStream;
00196 commit_stream->setcallback(WvStreamCallback(this,
00197 &UniConfd::commit_stream_cb), NULL);
00198 commit_stream->alarm(commit_interval * 1000);
00199 add_die_stream(commit_stream, true, "commit");
00200
00201 if (first_time)
00202 first_time = false;
00203 }
00204
00205 public:
00206
00207 UniConfd() :
00208 WvStreamsDaemon("uniconfd", VERBOSE_PACKAGE_VERSION,
00209 WvStreamsDaemonCallback(this, &UniConfd::startup)),
00210 needauth(false),
00211 port(DEFAULT_UNICONF_DAEMON_TCP_PORT),
00212 sslport(DEFAULT_UNICONF_DAEMON_SSL_PORT),
00213 commit_interval(5*60),
00214 first_time(true),
00215 permgen(NULL)
00216 {
00217 args.zap();
00218
00219 daemonize = true;
00220
00221 args.add_reset_bool_option('f', "foreground",
00222 "Run in foreground (non-forking)", daemonize);
00223 args.add_option('d', "debug",
00224 "Print debug messages (can be used multiple times)",
00225 WvArgs::NoArgCallback(this, &UniConfd::inc_log_level));
00226
00227 args.add_option(0, "pid-file",
00228 "Specify the .pid file to use", "filename",
00229 pid_file);
00230 args.add_set_bool_option('a', "need-auth",
00231 "Require authentication on incoming connections", needauth);
00232 args.add_option('A', "check-access",
00233 "Check all accesses against perms moniker", "moniker",
00234 permmon);
00235 args.add_option('p', "tcp",
00236 "Listen on given TCP port (default=4111; 0 to disable)", "port",
00237 port);
00238 args.add_option('s', "ssl",
00239 "Listen on given TCP/SSL port (default=4112; 0 to disable)", "port",
00240 sslport);
00241 #ifndef _WIN32
00242 args.add_option('u', "unix",
00243 "Listen on given Unix socket filename (default=disabled)", "filename",
00244 unixport);
00245 args.add_option('m', "unix-mode",
00246 "Set the Unix socket to 'mode' (default to uniconfd users umask)", "mode",
00247 unix_mode);
00248 args.add_option('n', "named-gen",
00249 "creates a \"named\" moniker 'name' from 'moniker'",
00250 "name=moniker",
00251 WvArgs::ArgCallback(this, &UniConfd::namedgen_cb), NULL);
00252 #endif
00253 args.add_optional_arg("MONIKERS", true);
00254 args.set_email("<" PACKAGE_BUGREPORT ">");
00255 }
00256
00257
00258 };
00259
00260 int main(int argc, char **argv)
00261 {
00262 UniConfd uniconfd;
00263
00264 return uniconfd.run(argc, argv);
00265 }