static void idlookup (str uid, str gid) { if (!uid) uid = "sfs"; if (!gid) gid = uid; bool uidok = convertint (uid, &sfs_uid); struct passwd *pw = uidok ? getpwuid (sfs_uid) : getpwnam (uid.cstr ()); bool gidok = convertint (gid, &sfs_gid); struct group *gr = gidok ? getgrgid (sfs_gid) : getgrnam (gid.cstr ()); if (!uidok) { if (!pw) fatal << "Could not find user " << uid << "\n"; sfs_uid = pw->pw_uid; } if (!gidok) { if (!gr) fatal << "Could not find group " << gid << "\n"; sfs_gid = gr->gr_gid; } if (gr && gr->gr_mem[0]) fwarn << "Group " << gid << " must not have any members\n"; if (pw && gr && (gid_t) pw->pw_gid != (gid_t) gr->gr_gid) fwarn << "User " << uid << " must have login group " << gid << ".\n"; endpwent (); endgrent (); }
static void start_server (int argc, char *argv[]) { int tcnt = 10; int maxq = 1000; int mysql_sth_method = 0; int ch; while ((ch = getopt (argc, argv, "t:q:ph")) != -1) switch (ch) { case 't': if (!convertint (optarg, &tcnt)) usage (); break; case 'q': if (!convertint (optarg, &maxq)) usage (); break; case 'p': mysql_sth_method = AMYSQL_PREPARED; break; default: usage (); } argc -= optind; argv += optind; #ifdef __clang_analyzer__ // Silences a value never read warning [[clang::unused]] auto const _unused = argv; #endif if (argc != 0) usage (); mtd_thread_typ_t method = MTD_NONE; #if HAVE_PTHREADS method = MTD_PTHREAD; #else # if HAVE_PTH method = MTD_PTH; # endif #endif ssrv_t *s = New ssrv_t (wrap (&tst2_srv_t::alloc, mysql_sth_method), tst2_prog_1, method, tcnt, maxq); json_XDR_dispatch_t::enable (); // turn off all warning messages s->mtd->set_quiet (true); if (!pub_server (wrap (s, &ssrv_t::accept), TST2_PORT)) fatal << "Cannot bind to port " << TST2_PORT << "\n"; }
static bool parse_service (vec<str> &av, extension *e, str errpref) { u_int32_t snum; str usage = strbuf () << errpref << ": usage: Service num prog [arg ...]\n" << errpref << ": Service num -u path\n" << errpref << ": Service num -t server [port]\n"; if (av.size () < 3 || !convertint (av[1], &snum)) { warn << usage; return false; } if (!e) { warn << errpref << ": Service must follow Release or Extensions\n"; return false; } if (e->srvtab[snum]) { warn << errpref << ": Service " << snum << " already defined\n"; return false; } av.pop_front (); av.pop_front (); if (av[0][0] != '-') { av[0] = fix_exec_path (av[0]); sfssrv *ss = exectab[av]; if (!ss) ss = New sfssrv_exec (av); e->srvtab.insert (snum, ss); return true; } else if (av[0] == "-u" && av.size () == 2) { sfssrv *ss = New sfssrv_sockpath (av[1]); e->srvtab.insert (snum, ss); return true; } else if (av[0] == "-t" && av.size () >= 2 && av.size () <= 3) { u_int16_t port = 0; if (av.size () == 2 || convertint (av[2], &port)) { sfssrv *ss = New sfssrv_proxy (av[1], port); e->srvtab.insert (snum, ss); return true; } } warn << usage; return false; }
bool str2cacheentry (sfsauth_cacheentry *ci, str s) { vec<str> cv; if (split (&cv, colon, s, 7, true) != 6) return false; ci->key = single_char_sub (cv[0], '$', ","); if (!parselist (&ci->values, cv[1], parsemember) || !convertint (cv[2], &ci->vers) || !convertint (cv[3], &ci->refresh) || !convertint (cv[4], &ci->timeout) || !convertint (cv[5], &ci->last_update)) return false; return true; }
// possible inputs: // // 400+c50 => 400, 401, 402 ... 449, 400, .... // 400+r50 => 443, 412, 403, 412, 414, 439 ... (i.e., random) // 400 => 400, 400, 400, 400, .... // => -1, -1, -1, .... // bool init (const str &s) { static rxx plus_rxx ("\\+"); _disabled = true; if (s.len () == 0) return true; vec<str> parts; if (split (&parts, plus_rxx, s) < 1) return false; // the first part of the expression is the constant offset if (parts.size () >= 1) { _disabled = false; _modulus = 1; _rand = false; if (!convertint (parts[0], &_offset)) return false; } // the second part tells how to cycle IDs. note that it is optional if (parts.size () == 2) { const char *cp = parts[1]; switch (*cp) { case 'c': _rand = false; break; case 'r': _rand = true; break; default: return false; } cp ++; if (!convertint (cp, &_modulus)) return false; } if (parts.size () > 2) return false; return true; }
int main (int argc, char *argv[]) { int port; if (argc != 3 || !convertint (argv[2], &port)) fatal << "usage: ex2 <hostname> <port>\n"; dostuff (argv[1], port, wrap (finish)); amain (); }
void sfskey_passwd (int argc, char *argv[]) { passwdcmd *pw = New passwdcmd (); u_int32_t opts = KM_FGEN; int ch; while ((ch = getopt (argc, argv, "KSpc:b:l:s:")) != -1) switch (ch) { case 'K': opts |= KM_NOKBD; break; case 'S': opts |= KM_NOSRP; break; case 'p': opts |= KM_PROAC; break; case 'c': if (!convertint (optarg, &pw->cost)) usage (); break; case 'b': if (!convertint (optarg, &pw->nbits)) usage (); break; case 's': pw->srpfile = optarg; break; case 'l': pw->keylabel = optarg; break; default: usage (); break; } pw->opts = opts; for (int i = optind; i < argc; i++) { pw->dest.push_back (argv[i]); } pw->start (); }
static void resvgidset (str lowstr, str highstr) { if (!lowstr || !highstr) return; u_int32_t end; if (!convertint (lowstr, &sfs_resvgid_start)) fatal << "Could not interpret resvgid value " << lowstr << " as a number.\n"; if (!convertint (highstr, &end)) fatal << "Could not interpret resvgid value " << highstr << " as a number.\n"; if (sfs_resvgid_start > end) fatal << "Starting value of resvgid range is greater than end value.\n"; sfs_resvgid_count = end - sfs_resvgid_start + 1; }
int main (int argc, char **argv) { setprogname (argv[0]); xputenv ("POSIXLY_CORRECT=1"); // Prevents Linux from reordering options sfsconst_init (); srp_base::minprimsize = sfs_mindlogsize; int ch; while ((ch = getopt (argc, argv, "S:p:vqV")) != -1) switch (ch) { case 'S': agentsock = optarg; break; case 'V': sfskey_version (); break; case 'p': { int fd; if (!convertint (optarg, &fd)) usage (); opt_pwd_fd = true; close_on_exec (fd); // Paranoia pwd_fds.push_back (fd); break; } case 'v': opt_verbose = true; break; case 'q': opt_quiet = true; break; default: usage (); break; } if (optind >= argc) usage (); const modevec *mp; for (mp = modes; mp->name; mp++) if (!strcmp (argv[optind], mp->name)) break; if (!mp->name) usage (); sfskey_mode = mp; optind++; mp->fn (argc, argv); amain (); }
bool to_hostname_and_port (const str &in, str *out, int *port) { bool ret = true; if (!host_and_port.match (in) || (host_and_port[3] && !convertint (host_and_port[3], port))) { ret = false; } else { *out = host_and_port[1]; } return ret; }
bool str2logentry (sfsauth_logentry *li, str s) { vec<str> lv; if (split (&lv, colon, s, 4, true) != 3) return false; if (!convertint (lv[0], &li->vers) || !parselist (&li->members, lv[1], parsemember)) return false; li->audit = lv[2]; return true; }
void sfs_hosttab_t::loadfd (int fd) { suio uio; int lineno = 0; sfs_sa sa; bzero (&sa, sizeof (sa)); sa.sa_in.sin_family = AF_INET; for (;;) { lineno++; size_t n; while (!(n = uio.linelen ())) if (uio.input (fd) <= 0) { if (uio.resid ()) errmsg (lineno, "incomplete last line"); return; } mstr m (n); uio.copyout (m, n - 1); m[n-1] = '\0'; uio.rembytes (n); if (m[0] == '#' || m[0] == '\n') continue; char *p = m; char *host = strnnsep (&p, " \t\r\n"); char *port = host; xstrsep (&port, "%"); if (inet_aton (host, &sa.sa_in.sin_addr) <= 0) { errmsg (lineno, "invalid IP address"); continue; } if (!port || !*port) sa.sa_in.sin_port = htons (SFS_PORT); else if (convertint (port, &sa.sa_in.sin_port)) sa.sa_in.sin_port = htons (sa.sa_in.sin_port); else { errmsg (lineno, "invalid port number"); continue; } while ((host = strnnsep (&p, " \t\r\n"))) { str h (mytolower (host)); if (sfs_host *hp = tab[h]) delete hp; tab.insert (New sfs_host (h, sa, sizeof (sa.sa_in))); } } }
int main (int argc, char *argv[]) { setprogname (argv[0]); if (argc != 2 && argc !=3) usage (); str s = file2str (argv[1]); int off = -1; if (argc == 3 && !convertint (argv[2], &off)) usage (); if (!s) fatal << "cannot open file: " << argv[1]; const char *cp = strstr (s.cstr (), "\r\n\r\n"); if (!cp) fatal << "file is not a raw HTTP dump: " << argv[1]; cp += 4; size_t sz; Bytef outbuf[100000]; uLong outlen = 100000; int rc = -1; u_int i = 0; Bytef b2[100000]; Bytef *bp = b2; u_int t = 0; while ((sz = getsize (&cp)) > 0) { /* for (i = 0; i < sz && rc < 0; i++) { for (j = sz; j >= 0 && rc < 0; j--) { rc = uncompress (outbuf, &outlen, reinterpret_cast<const Bytef *> (cp+i), j); warn ("%d,%d,%d,%x,%x\n", i, j, rc, char (cp[i]), char (cp[i+1])); } } */ memcpy (bp, cp, sz); bp += sz; t += sz; cp += (2 + sz); } rc = myunc (outbuf, &outlen, reinterpret_cast<const Bytef *> (b2+10), t - 10); if (rc < 0) fatal << "uncompress failed: " << rc << "\n"; warn << "eureka!!! " << i << "\n"; if (write (1, outbuf, outlen) < int (outlen)) fatal << "short write.\n"; exit (0); }
bool str2groupinfo (sfsauth_groupinfo *gi, str s) { vec<str> gv; if (split (&gv, colon, s, 8, true) != 7) return false; if (!namerx.match (gv[0]) || badcharrx.search (gv[5])) return false; gi->name = gv[0]; if (!convertint (gv[1], &gi->id) || !convertint (gv[2], &gi->vers) || !parselist (&gi->owners, gv[3], parsemember) || !parselist (&gi->members, gv[4], parsemember) // || !convertint (gv[5], &gi->refresh) // || !convertint (gv[6], &gi->timeout) ) return false; gi->properties = gv[5]; gi->audit = gv[6]; // gi->audit = gv[7]; return true; }
bool parse_hn (const str &in, str *host, int *port) { static rxx host_port_rxx ("([.0-9A-Za-z_-]*)(:[0-9]+)?"); if (!host_port_rxx.match (in)) return false; str h = host_port_rxx[1]; if (h && h.len () > 0 && h != "-") *host = h; str p = host_port_rxx[2]; if (p && p.len () > 1) { const char *pc = p.cstr () + 1; p = pc; if (!convertint (p, port)) return false; } return true; }
int main (int argc, char **argv) { setprogname (argv[0]); bool opt_force = false; int ch; while ((ch = getopt (argc, argv, "ft:")) != -1) switch (ch) { case 'f': opt_force = true; break; case 't': if (!convertint (optarg, &timeout)) usage (); break; default: usage (); break; } argc -= optind; argv += optind; if (argc != 2) usage (); struct sigaction sa; bzero (&sa, sizeof (sa)); sa.sa_handler = cleanup; #ifdef SA_RESETHAND sa.sa_flags = SA_NODEFER | SA_RESETHAND; #endif /* SA_RESETHAND */ sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sigaction (SIGALRM, &sa, NULL); if (!opt_force && !outofdate (argv[0], argv[1])) exit (0); docopy (argv[0], argv[1]); warn ("copied %s -> %s\n", argv[0], argv[1]); return 0; }
bool mtd_reporting_t::set_rpc_reports (const str &s) { bool ok = true; static rxx x ("\\s*,\\s*"); _rpcs.clear (); if (s) { vec<str> v; split (&v, x, s); for (size_t i = 0; i < v.size (); i++) { int tmp; if (convertint (v[i], &tmp)) { _rpcs.insert (tmp); } else { ok = false; warn << "Bad RPC number specified for reporting: " << v[i] << "\n"; } } } return ok; }
bool str2authdbrec (sfsauth_dbrec *dbr, str s) { static rxx _userrx ("^USER:(.*)$"); rxx userrx (_userrx); static rxx grouprx ("^GROUP:(.*)$"); static rxx cacherx ("^CACHE:(.*)$"); static rxx logrx ("^LOG:(.*)$"); static rxx revinfo ("^REVINFO:([0-9a-fA-F]+):(\\d+)$"); if (revinfo.match (s)) { str id = hex2bytes (revinfo[1]); u_int64_t rev; if (!id || id.len () != sizeof (dbr->revinfo->dbid) || !convertint (revinfo[2], &rev)) return false; dbr->set_type (SFSAUTH_REVINFO); dbr->revinfo->dbrev = rev; memcpy (dbr->revinfo->dbid.base (), id, id.len ()); return true; } else if (userrx.match (s)) { dbr->set_type (SFSAUTH_USER); return str2userinfo (dbr->userinfo, str2wstr (userrx[1])); } else if (grouprx.match (s)) { dbr->set_type (SFSAUTH_GROUP); return str2groupinfo (dbr->groupinfo, grouprx[1]); } else if (cacherx.match (s)) { dbr->set_type (SFSAUTH_CACHEENTRY); return str2cacheentry (dbr->cacheentry, cacherx[1]); } else if (logrx.match (s)) { dbr->set_type (SFSAUTH_LOGENTRY); return str2logentry (dbr->logentry, logrx[1]); } else return false; }
static bool parseconfig (const char *dir, const char *file) { str cf; if (!file) return false; if (file[0] == '/') cf = file; else if (!dir) return false; else cf = strbuf ("%s/%s", dir, file); if (access (cf, F_OK) < 0) { if (errno != ENOENT) warn << cf << ": " << strerror (errno) << "\n"; return false; } conftab ct; bool dirset = false; ct.add ("RSASize", &sfs_rsasize, sfs_minrsasize, sfs_maxrsasize) .add ("DLogSize", &sfs_dlogsize, sfs_mindlogsize, sfs_maxdlogsize) .add ("PwdCost", &sfs_pwdcost, 0, 32) .add ("LogPriority", &syslog_priority) .add ("sfsdir", wrap (&got_sfsdir, &dirset)); str uid, gid, nuid, ngid, resvgidlow, resvgidhigh; bool errors = false; parseargs pa (cf); int line; vec<str> av; while (pa.getline (&av, &line)) { if (!strcasecmp (av[0], "sfsuser")) { if (uid) { errors = true; warn << cf << ":" << line << ": Duplicate sfsuser directive\n"; } else if (av.size () == 2) uid = gid = av[1]; else if (av.size () == 3) { uid = av[1]; gid = av[2]; } else { errors = true; warn << cf << ":" << line << ": usage: sfsuser user [group]\n"; } } else if (!strcasecmp (av[0], "anonuser")) { if (nuid) { errors = true; warn << cf << ":" << line << ": Duplicate anonuser directive\n"; } else if (av.size () == 2) nuid = av[1]; else if (av.size () == 3) { nuid = av[1]; ngid = av[2]; } else { errors = true; warn << cf << ":" << line << ": usage: anonuser user [group]\n"; continue; } gid_t g; if (ngid) { if (!convertint (ngid, &g)) { if (struct group *gr = getgrnam (ngid)) g = gr->gr_gid; else { errors = true; warn << cf << ":" << line << ": no group " << ngid << "\n"; ngid = NULL; } } } uid_t u; if (!convertint (nuid, &u)) { struct passwd *pw = getpwnam (nuid); if (!pw) { errors = true; warn << cf << ":" << line << ": no user " << nuid << "\n"; continue; } nobody_uid = pw->pw_uid; if (ngid) nobody_gid = g; else nobody_gid = pw->pw_gid; } else if (ngid) { nobody_uid = u; nobody_gid = g; } else { errors = true; warn << cf << ":" << line << ": Must specify gid with numeric uid"; continue; } } else if (!strcasecmp (av[0], "resvgids")) { if (resvgidhigh) { errors = true; warn << cf << ":" << line << ": Duplicate resvgids directive\n"; } else if (av.size () != 3) { errors = true; warn << cf << ":" << line << ": usage: resvgids lower upper\n"; } else { resvgidlow = av[1]; resvgidhigh = av[2]; } } else if (!ct.match (av, cf, line, &errors)) { warn << cf << ":" << line << ": Unknown directive '" << av[0] << "'\n"; } } if (errors) warn << "errors in " << cf << "\n"; if (uid) idlookup (uid, gid); resvgidset (resvgidlow, resvgidhigh); return true; }
void sfskey_group (int argc, char **argv) { groupcmd *gc = New groupcmd (); int ch; while ((ch = getopt (argc, argv, "L:ECa:m:o:")) != -1) switch (ch) { case 'a': gc->keys.push_back (optarg); break; case 'm': if (optarg[0] != '+' && optarg[0] != '-') { warn ("Member names must begin with + (add) or - (remove)\n"); usage (); } if (strlen (optarg) > sfs_groupmember::maxsize) { warn ("Member name is too long (max 256 characters): %s\n", optarg); usage (); } gc->members.push_back (optarg); break; case 'o': if (optarg[0] != '+' && optarg[0] != '-') { warn ("Owner names must begin with + (add) or - (remove)\n"); usage (); } if (strlen (optarg) > sfs_groupmember::maxsize) { warn ("Owner name is too long (max 256 characters): %s\n", optarg); usage (); } gc->owners.push_back (optarg); break; case 'C': gc->create = true; break; case 'E': gc->expanded = true; break; case 'L': if (!convertint (optarg, &gc->version) || gc->version < 0) usage (); break; default: usage (); break; } if ((optind + 1 != argc) || (!sfsgroupmgr::parsegroup (argv[optind], &gc->gname, &gc->ghost))) usage (); gc->group = argv[optind]; if (!(gc->ghost == "-") && issrpkey (gc->ghost)) gc->keys.push_back (srp_prepend (gc->ghost)); if (gc->members.size () == 0 && gc->owners.size () == 0) if (gc->create) gc->update (); else if (gc->version >= 0) { if (gc->expanded) warn << "Expanded (-E) option doesn't apply to changelog queries. Ignoring...\n"; gc->changelog (); } else gc->query (); else { if (gc->expanded) warn << "Expanded (-E) option doesn't apply to updates. Ignoring...\n"; if (gc->version >= 0) warn << "Changelog (-L) option doesn't apply to updates. Ignoring...\n"; if (gc->owners.size () > 250) fatal << "Owners list is too big (> 250 entries) for a single update\n" << "and I don't want to split it up arbitrarily. Please issue\n" << "multiple `sfskey group' commands with the owners list split\n" << "up to provide the correct permissions semantics.\n"; if (gc->create) fatal << "Cannot use Create (-C) option with an owners/members list.\n"; gc->update (); } }
void hclient_t::do_read () { int rc = uio.input (fd); if (rc == 0 && !output_stuff) { stats.empties ++; warn ("no content before EOF\n"); cexit (-1); return;; } else if (rc == 0) { // legitimate EOF cexit (0); return; } else if (rc == -1) { if (errno != EAGAIN) { stats.read_errors ++ ; warn ("read error: %m\n"); cexit (-1); } return; } assert (rc > 0); // for sane Web servers, this is easy... if (mode != SEDA) { while (uio.resid ()) { output_stuff = true; uio.output (1); } return; } // // for SEDA, we've had to parse the header and cut off the // connection, since it doesn't support closed connections // as we've asked. // rc = uio.copyout (bp); uio.rembytes (rc); bp += rc; // // reqsz < 0 if we haven't found a field yet in the header // if (reqsz < 0) { if (sz_rxx.search (buf)) { if (!convertint (sz_rxx[1], &reqsz)) { warn ("invalid length: %s\n", sz_rxx[1].cstr ()); cexit (-1); } } } if (!body) body = strstr (buf, "\r\n\r\n"); // // if we've seen the required number of bytes (as given by // the header) then we're ready to close (or rock!) // if (body && (bp - body >= reqsz)) { rc_ignore (write (1, buf, bp - buf)); if (noisy) warn ("ok, closing up!\n"); cexit (0); } }
int main (int argc, char *argv[]) { timeout = 120; noisy = false; zippity = false; srandom(time(0)); setprogname (argv[0]); int ch; int n = 1000; nconcur = 500; bool delay = false; timespec startat; startat.tv_nsec = 0; startat.tv_sec = 0; exited = false; hclient_id = 1; use_latencies = false; num_services = 1; tpt_sample_period_secs = 1; tpt_sample_period_nsecs = 0; int lat_stddv = 25; int lat_mean = 75; lose_patience_after = 0; id_cycler_t *svc_cycler = NULL; id_cycler_t *req_cycler = NULL; mode = NONE; bool no_pub = false; int tmp = 0; static rxx lose_patience_rxx ("(\\d+),(\\d+)"); while ((ch = getopt (argc, argv, "c:dlm:n:pr:t:v:zM:P:S:R:T:V:")) != -1) { switch (ch) { case 'c': if (!convertint (optarg, &nconcur)) usage (); if (noisy) warn << "Concurrency factor: " << nconcur << "\n"; break; case 'd': noisy = true; break; case 'l': use_latencies = true; if (noisy) warn << "Using Latencies\n"; break; case 'm': { switch (optarg[0]) { case 's': case 'S': mode = SEDA; if (noisy) warn << "In SEDA mode\n"; break; case 'o': case 'O': mode = OKWS; if (noisy) warn << "In OKWS mode\n"; break; case 'P': case 'p': mode = PHP; if (noisy) warn << "In PHP mode\n"; break; case 'f': case 'F': mode = FLASH; if (noisy) warn << "In FLASH mode\n"; break; default: usage (); break; } break; } case 'n': if (!convertint (optarg, &n)) usage (); if (noisy) warn << "Number of requests: " << n << "\n"; break; case 'p': no_pub = true; break; case 'r': if (!convertint (optarg, &tmp)) usage (); req_cycler = New id_cycler_t (true, tmp, 1); if (noisy) warn << "Ranging ids from 1 to " << tmp << " (randomly)\n"; break; case 't': { if (!convertint (optarg, &startat.tv_sec)) usage (); delay = true; if (noisy) warn << "Delaying start until time=" << startat.tv_sec << "\n"; time_t mytm = time (NULL); tmp = startat.tv_sec - mytm; if (tmp < 0) { warn << "time stamp alreached (it's " << mytm << " right now)!\n"; usage (); } if (noisy) { warn << "Starting in T minus " << tmp << " seconds\n"; } break; } case 'v': if (!convertint (optarg, &tmp)) usage (); svc_cycler = New id_cycler_t (true, tmp, 1); if (noisy) warn << "Randing services from 1 to " << tmp << " (randomly)\n"; break; case 'z': zippity = true; break; case 'M': if (!convertint (optarg, &lat_mean)) usage (); if (noisy) warn << "Mean of latencies: " << lat_mean << "\n"; break; case 'P': if (!convertint (optarg, &tmp)) usage (); tpt_sample_period_secs = tmp / THOUSAND; tpt_sample_period_nsecs = (tmp % THOUSAND) * MILLION; if (noisy) warn ("Sample throughput period=%d.%03d secs\n", tpt_sample_period_secs, tpt_sample_period_nsecs / MILLION); break; case 'R': req_cycler = New id_cycler_t (); if (!req_cycler->init (optarg)) usage (); break; case 'S': if (!convertint (optarg, &lat_stddv)) usage (); if (noisy) warn << "Standard dev. of latency: " << lat_stddv << "\n"; break; case 'T': if (!lose_patience_rxx.match (optarg) || !convertint (lose_patience_rxx[1], &n_still_patient) || !convertint (lose_patience_rxx[2], &lose_patience_after)) usage (); break; case 'V': svc_cycler = New id_cycler_t (); if (!svc_cycler->init (optarg)) usage (); break; default: usage (); } } argc -= optind; argv += optind; if (argc == 0) usage (); str dest = argv[0]; argc --; argv ++; // make the appropriate cyclers... if (argc > 0) { // in this case, the user supplied extra arguments after the hostname // and port; therefore, they're going to be making their own URL // by alternating static parts and cyclers. if (req_cycler) { warn << "Don't provide -r if you're going to make your own URI\n"; usage (); } if (svc_cycler) { warn << "Don't provide -v if you're going to make your own URI\n"; usage (); } for (int i = 0; i < argc; i++) { if (i % 2 == 0) { uri_parts.push_back (argv[i]); } else { id_cycler_t *tmp = New id_cycler_t (); if (!tmp->init (argv[i])) { warn << "Cannot parse ID cycler: " << argv[i] << "\n"; usage (); } id_cyclers.push_back (tmp); } } } else if (mode != NONE) { // no manual URL building required; just specify some defaults // though if none were specified if (!req_cycler) // roughly a million, but this way all reqs will have the same // number of digits req_cycler = New id_cycler_t (true, 900000, 100000); if (!svc_cycler) // don't cycle --- just always return 1 svc_cycler = New id_cycler_t (false, 1, 1); id_cyclers.push_back (svc_cycler); id_cyclers.push_back (req_cycler); switch (mode) { case SEDA: uri_parts.push_back ("mt"); uri_parts.push_back ("?id="); break; case OKWS: { uri_parts.push_back ("mt"); strbuf b ("?"); if (no_pub) b << "nopub=1&"; b << "id="; uri_parts.push_back (b); break; } case PHP: uri_parts.push_back ("mt"); uri_parts.push_back (".php?id="); break; case FLASH: uri_parts.push_back ("cgi-bin/mt"); uri_parts.push_back ("?"); break; default: break; } } // normdist (mean, std-dev, "precision") if (use_latencies) dist = New normdist_t (200,25); if (!hostport.match (dest)) usage (); host = hostport[1]; str port_s = hostport[3]; if (port_s) { if (!convertint (port_s, &port)) usage (); } else { port = 80; } struct timespec tsnow = sfs_get_tsnow (); // unless we don this, shit won't be initialized, and i'll // starting ripping my hair out as to why all of the timestamps // are negative clock_gettime (CLOCK_REALTIME, &tsnow); nrunning = 0; sdflag = true; nreq = n; nreq_fixed = n; tpt_last_nreq = nreq; if (delay) { timecb (startat, wrap (main2, n)); } else { main2 (n); } amain (); }
int main (int argc, char **argv) { setprogname (argv[0]); if (argc != 4 || !convertint (argv[1], &shmfd) || !convertint (argv[2], &rfd) || !convertint (argv[3], &rwfd)) usage (); #ifdef MAINTAINER if (getenv ("AIOD_PAUSE")) { struct sigaction sa; bzero (&sa, sizeof (sa)); sa.sa_handler = nop; #ifdef SA_RESETHAND sa.sa_flags = SA_RESETHAND; #endif /* SA_RESETHAND */ sigaction (SIGCONT, &sa, NULL); warn ("pid %d, pausing\n", int (getpid ())); timeval tv; tv.tv_sec = 60; tv.tv_usec = 0; select (0, NULL, NULL, NULL, &tv); } #endif /* MAINTAINER */ umask (0); ptr<shmbuf> b = shmbuf::alloc (shmfd); if (!b) fatal ("could not map shared memory buffer\n"); srv = New aiosrv (rwfd, b); (void) sigemptyset (&sigio_mask); sigaddset (&sigio_mask, SIGIO); sigprocmask (SIG_BLOCK, &sigio_mask, NULL); struct sigaction sa; bzero (&sa, sizeof (sa)); sa.sa_handler = sigio_handler; if (sigaction (SIGIO, &sa, NULL) < 0) fatal ("sigaction: %m\n"); /* Since the client code might not necessarily tolerate the death of * an aiod process, put ourselves in a new process group. That way * if the parent process catches terminal signals like SIGINT, the * aiods will not die. This allows the parent still to issue aio * requests while handling the signal. Additionally, if sigio_set * uses SIOCSPGRP, starting a new process group avoids hitting other * processes with our SIGIO signals. */ setpgid (0, 0); if (sigio_set (rwfd) < 0) fatal ("could not enable SIGIO\n"); msg_loop (); return 1; }
int main (int argc, char **argv) { setprogname (argv[0]); random_update (); create_mode = false; add_mode = false; wind_mode = false; unwind_mode = false; error_check = true; window_mode = false; verbose_mode = false; id = 0; keysize = 16; chainlen = 128; window_startvers = 0; protocol = strbuf () << "sha1"; type = SFSRO_SHA1; directory = NULL; outfile = NULL; int ch; while ((ch = getopt (argc, argv, "i:k:p:d:o:l:W:cawumv")) != -1) switch (ch) { case 'i': if (!convertint (optarg, &id)) usage (); break; case 'k': if (!convertint (optarg, &keysize) || keysize < 16 || keysize > 32) usage (); break; case 'p': protocol = optarg; if (protocol == "sha1") type = SFSRO_SHA1; else if(protocol == "rabin") type = SFSRO_RABIN; else usage (); break; case 'd': directory = optarg; break; case 'o': outfile = optarg; break; case 'c': create_mode= true; break; case 'a': add_mode= true; break; case 'w': wind_mode= true; break; case 'u': unwind_mode= true; break; case 'l': if (!convertint (optarg, &chainlen)) usage (); break; case 'W': if (!convertint (optarg, &window_startvers)) usage (); break; case 'm': window_mode = true; break; case 'v': verbose_mode = true; break; default: usage (); } argc -= optind; argv += optind; if ( (argc > 0) || !directory || !id || ((create_mode + add_mode + wind_mode + unwind_mode) != 1) || !(create_mode || !window_mode)) usage (); kro = New refcounted<keyregression_owner> (directory, id, type, keysize, chainlen, create_mode, window_mode, verbose_mode); if (add_mode) { if (!kro->add (outfile, window_startvers, verbose_mode)) { warn << "kro->add failed\n"; exit (1); } } if (wind_mode) { if (!kro->wind (outfile, verbose_mode)) { warn << "kro->wind failed\n"; exit (1); } } /* if (unwind_mode) { if (!kro->unwind (outfile)) { warn << "kro->unwind failed\n"; exit (1); } } */ }
static void parseconfig () { str cf = configfile; parseargs pa (cf); bool errors = false; str hostname; rpc_ptr<sfs_hash> hostid; server *s = NULL; release *r = NULL; extension *e = NULL; char *c; int line; vec<str> av; while (pa.getline (&av, &line)) { if (!strcasecmp (av[0], "BindAddr")) { in_addr addr; u_int16_t port = 0; if (av.size () < 2 || av.size () > 3 || !inet_aton (av[1], &addr) || (av.size () == 3 && !convertint (av[2], &port))) { warn << cf << ":" << line << ": usage: BindAddr addr [port]\n"; errors = true; continue; } if (!port) port = sfs_defport ? sfs_defport : SFS_PORT; sockaddr_in *sinp = static_cast<sockaddr_in *> (xmalloc (sizeof (*sinp))); bzero (sinp, sizeof (*sinp)); sinp->sin_family = AF_INET; sinp->sin_port = htons (port); sinp->sin_addr = addr; #ifdef HAVE_SA_LEN sinp->sin_len = sizeof (*sinp); #endif /* HAVE_SA_LEN */ listenaddrs.push_back (reinterpret_cast<sockaddr *> (sinp)); } else if (!strcasecmp (av[0], "Server")) { if (av.size () != 2) { warn << cf << ":" << line << ": usage: Server {hostname|*}[:hostid]\n"; errors = true; continue; } if (strchr (av[1], ':') || ((c = strchr (av[1], '@')) && strchr (c, ','))) { hostid.alloc (); if (!sfs_parsepath (av[1], &hostname, hostid)) { warn << cf << ":" << line << ": bad hostname/hostid\n"; errors = true; continue; } } else { hostid.clear (); if (av[1] == "*") hostname = sfshostname (); else hostname = av[1]; } for (s = serverlist.first; s; s = serverlist.next (s)) if (hostname == s->host && ((hostid && s->hostid && *hostid == *s->hostid) || (!hostid && !s->hostid))) break; if (!s) s = New server (hostname, hostid); r = NULL; e = NULL; } else if (!strcasecmp (av[0], "Release")) { static rxx relrx ("^(\\d+)\\.(\\d\\d?)$"); if (av.size () != 2 || (!relrx.search (av[1]) && av[1] != "*")) { warn << cf << ":" << line << ": usage Release { N.NN | * }\n"; errors = true; r = NULL; continue; } if (!s) { warn << cf << ":" << line << ": Release must follow Server\n"; errors = true; r = NULL; continue; } u_int32_t rel; if (av[1] == "*") rel = 0xffffffff; else rel = strtoi64 (relrx[1]) * 100 + strtoi64 (relrx[2]); r = s->reltab[rel]; if (!r) s->reltab.insert ((r = New release (rel))); for (e = r->extlist.first; r->extlist.next (e); e = r->extlist.next (e)) ; } else if (!strcasecmp (av[0], "Extensions")) { av.pop_front (); e = r->getext (av); } else if (!strcasecmp (av[0], "Service")) { if (!parse_service (av, e, cf << ":" << line)) errors = true; } else if (!strcasecmp (av[0], "HashCost")) { if (av.size () != 2 || !convertint (av[1], &sfs_hashcost)) { warn << cf << ":" << line << ": usage: HashCost <nbits>\n"; errors = true; } else { if (sfs_hashcost > sfs_maxhashcost) sfs_hashcost = sfs_maxhashcost; str s (strbuf ("SFS_HASHCOST=%d", sfs_hashcost)); xputenv (const_cast<char*>(s.cstr())); } } else if (!strcasecmp (av[0], "RevocationDir")) { if (av.size () != 2) { warn << cf << ":" << line << ": usage: RevocationDir <directory>\n"; errors = true; } else { revocationdir = av[1]; } } else { errors = true; warn << cf << ":" << line << ": unknown directive '" << av[0] << "'\n"; } } if (errors) fatal ("parse errors in configuration file\n"); }
static bool parsenum (u_int32_t *nump, str s) { return convertint (s, nump); }
bool str2userinfo (sfsauth_userinfo *ui, str s) { str name; vec<str> uv; if (split (&uv, colon, s, 12, true) != 11) return false; str2wstr (uv[7]); str2wstr (uv[8]); str fields[13] = { "name", "uid", "version", "gid", "owner", "pubkey", "privs", "srp", "privkey", "srvprivkey", // "refresh", "timeout", "audit" }; if (!namerx.match (uv[0])) { err_report ("<null>", 1, fields[0], uv[0]); return false; } name = uv[0]; for (int i = 1; i < 4; i++) { if (!decrx.match (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } if (uv[4].len () && !namerx.match (uv[4])) { err_report (name, 5, fields[4], uv[4]); return false; } for (int i = 6; i < 10; i++) { if (badcharrx.search (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } #if 0 for (int i = 10; i < 12; i++) { if (!decrx.match (uv[i])) { err_report (name, i+1, fields[i], uv[i]); return false; } } #endif str privkey = dearmor64 (uv[8]); if (!privkey) { err_report (name, 9, fields[8], "could not dearmor64"); return false; } str2wstr (privkey); ui->privkey.setsize (privkey.len ()); memcpy (ui->privkey.base (), privkey, ui->privkey.size ()); ui->name = uv[0]; if (!convertint (uv[1], &ui->id) || !convertint (uv[2], &ui->vers) || !convertint (uv[3], &ui->gid) // || !convertint (uv[10], &ui->refresh) // || !convertint (uv[11], &ui->timeout) ) return false; if (uv[4].len ()) *ui->owner.alloc () = uv[4]; else ui->owner.clear (); ptr<sfspub> pk = sfscrypt.alloc (uv[5]); if (!pk) return false; if (!pk->export_pubkey (&ui->pubkey)) { warn << "Cannot load keypair for " << uv[0] << "\n"; return false; } ui->privs = uv[6]; ui->pwauth = uv[7]; if (uv[9] && uv[9].len ()) { if (!sfs_2schnorr_priv::parse_keyhalf (&ui->srvprivkey, uv[9])) { warn << "Cannot load server keyhalf for " << uv[0] << "\n"; return false; } } else { ui->srvprivkey.set_type (SFSAUTH_KEYHALF_NONE); } // ui->audit = uv[12]; ui->audit = uv[10]; return true; }
void sfsconst_init (bool lite_mode) { if (const_set) return; const_set = true; { char *p = safegetenv ("SFS_RELEASE"); if (!p || !convertint (p, &sfs_release)) { str rel (strbuf () << "SFS_RELEASE=" << sfs_release); xputenv (const_cast<char*>(rel.cstr())); } } #ifdef MAINTAINER if (char *p = safegetenv ("SFS_RUNINPLACE")) { runinplace = true; builddir = p; buildtmpdir = builddir << "/runinplace"; } if (char *p = safegetenv ("SFS_ROOT")) if (*p == '/') sfsroot = p; #endif /* MAINTAINER */ sfsdevdb = strbuf ("%s/.devdb", sfsroot); #ifdef MAINTAINER if (runinplace) { sfsdir = buildtmpdir; sfssockdir = sfsdir; etc3dir = etc1dir; etc1dir = sfsdir.cstr(); etc2dir = xstrdup (str (builddir << "/etc")); } #endif /* MAINTAINER */ if (char *ps = safegetenv ("SFS_PORT")) if (int pv = atoi (ps)) sfs_defport = pv; str sfs_config = safegetenv ("SFS_CONFIG"); if (sfs_config && sfs_config[0] == '/') { if (!parseconfig (NULL, sfs_config)) fatal << sfs_config << ": " << strerror (errno) << "\n"; } else { if (!parseconfig (etc3dir, sfs_config)) { parseconfig (etc3dir, "sfs_config"); if (!parseconfig (etc2dir, sfs_config)) { parseconfig (etc2dir, "sfs_config"); if (!parseconfig (etc1dir, sfs_config)) parseconfig (etc1dir, "sfs_config"); } } } if (!lite_mode) { if (!sfs_uid) idlookup (NULL, NULL); } if (char *p = getenv ("SFS_HASHCOST")) { sfs_hashcost = strtoi64 (p); if (sfs_hashcost > sfs_maxhashcost) sfs_hashcost = sfs_maxhashcost; } if (!getuid () && !runinplace) { mksfsdir (sfsdir, 0755); mksfsdir (sfssockdir, 0750); } else if (runinplace && access (sfsdir, 0) < 0) { struct stat sb; if (!stat (builddir, &sb)) { mode_t m = umask (0); if (!getuid ()) { if (pid_t pid = fork ()) waitpid (pid, NULL, 0); else { umask (0); setgid (sfs_gid); setuid (sb.st_uid); if (mkdir (sfsdir, 02770) >= 0) rc_ignore (chown (sfsdir, (uid_t) -1, sfs_gid)); _exit (0); } } else mkdir (sfsdir, 0777); umask (m); } } }
void authclnt::update_group (svccb *sbp, update_info &i) { dbfile *udbp; ptr<authcursor> uac; sfsauth_dbrec udbr; *i.kname.name = i.argp->req.rec.groupinfo->name; bool create = i.argp->req.rec.groupinfo->id == 0 && i.argp->req.rec.groupinfo->vers == 1; bool exists = get_group_cursor (&udbp, &uac, &udbr, i.kname, true, create); if (exists && create && udbr.groupinfo->id > udbp->grprange->id_max) { *i.res.errmsg = strbuf () << "all group IDs in the allowed range (" << udbp->grprange->id_min << "-" << udbp->grprange->id_max << ") are in use"; return; } if (!exists) { if (!create) { *i.res.errmsg = "perhaps record is read-only " "or database doesn't accept group updates"; return; } else { *i.res.errmsg = "no writable databases that accept group updates"; return; } } if (create && udbr.groupinfo->vers != 0) { *i.res.errmsg = strbuf () << "group `" << udbr.groupinfo->name << "'already exists"; return; } if (!i.admin) { if (create) { str gname; if (!(gname = group_prefix (udbr.groupinfo->name, i.cdbr.userinfo->name)) || gname.len () < 1) { *i.res.errmsg = strbuf () << "group name must be of the form `" << i.cdbr.userinfo->name << ".groupname'"; return; } static rxx groupquotarx ("(\\A|,)groupquota=([0-9]+)(\\Z|,)"); if (groupquotarx.search (i.cdbr.userinfo->privs) || udbp->default_groupquota >= 0) { u_int32_t max_groups; u_int32_t cur_groups; if (groupquotarx.success ()) convertint (groupquotarx[2], &max_groups); else max_groups = udbp->default_groupquota; // XXX - open could fail ptr<authcursor> gac = udbp->db->open (udbp->dbflags); cur_groups = gac->count_group_prefix (strbuf () << i.cdbr.userinfo->name << "."); if (cur_groups + 1 > max_groups) { *i.res.errmsg = strbuf () << "group quota exceeded (current=" << cur_groups << "/quota=" << max_groups << ")"; return; } } } else { ptr<sfspub> pk = sfscrypt.alloc (i.cdbr.userinfo->pubkey); str h = armor32 (pk->get_pubkey_hash ()); sfs_groupmembers list; unsigned int n = udbr.groupinfo->owners.size (); for (unsigned int j = 0; j < n; j++) list.push_back (udbr.groupinfo->owners[j]); if (!group_prefix (udbr.groupinfo->name, i.cdbr.userinfo->name) && !is_a_member (i.cdbr.userinfo->name, h, list)) { *i.res.errmsg = "access denied"; return; } } } if (i.argp->req.rec.groupinfo->vers < 1) { *i.res.errmsg = "version number of record must be greater than 0"; return; } if (i.argp->req.rec.groupinfo->vers != udbr.groupinfo->vers + 1) { *i.res.errmsg = "version mismatch"; return; } uac->ae.groupinfo->vers = i.argp->req.rec.groupinfo->vers; strbuf sb; sb << "Last modified " << timestr () << " by " ; if (uid && !*uid) sb << "*superuser*"; else sb << i.cp->unixcred->username; sb << "@" << client_name; uac->ae.groupinfo->audit = sb; // XXX: checking to make sure that the owners/groups are well-formed happens in update process_group_updates (udbr.groupinfo->owners, i.argp->req.rec.groupinfo->owners); process_group_updates (udbr.groupinfo->members, i.argp->req.rec.groupinfo->members); uac->ae.groupinfo->owners = udbr.groupinfo->owners; uac->ae.groupinfo->members = udbr.groupinfo->members; bool chlogok = write_group_changelog (i.argp->req.rec.groupinfo->name, i.argp->req.rec.groupinfo->vers, i.argp->req.rec.groupinfo->members, sb); if (!chlogok) { *i.res.errmsg = "could not write changelog; database unmodified"; return; } if (!uac->update ()) { // XXX: remove changelog entry *i.res.errmsg = "database refused update; see SFS documentation for correct syntax"; return; } i.res.set_ok (true); udbp->mkpub (); uac->find_group_name (udbr.groupinfo->name); if (global_dbcache) update_dbcache (uac); }
int main (int argc, char **argv) { #ifdef MAINTAINER if (getenv ("SFS_RUNINPLACE")) { setgid (getgid ()); setuid (getuid ()); } #endif /* MAINTAINER */ setprogname (argv[0]); sfsconst_init (); const uid_t procuid = getuid (); uid_t newuid = procuid; uid_t uid = myaid () & INT64 (0xffffffff); gid_t gid; bool opt_gid = false; bool opt_login = false; bool opt_nogid = false; bool opt_U = false; str opt_chdir; size_t num_u = 0; int ch; while ((ch = getopt (argc, argv, "lu:U:g:GC:")) != -1) switch (ch) { case 'l': opt_login = true; break; case 'u': if (num_u++ || !convertint (optarg, &uid)) usage (); break; case 'U': if (num_u++ || !convertint (optarg, &newuid)) usage (); uid = newuid; opt_U = true; break; case 'g': if (opt_nogid || !convertint (optarg, &gid)) usage (); opt_gid = true; break; case 'G': if (opt_gid) usage (); opt_nogid = true; case 'C': if (opt_chdir) usage (); opt_chdir = optarg; break; default: usage (); } argc -= optind; argv += optind; if (procuid && (newuid != procuid || uid != procuid)) fatal ("only root can change uids.\n"); if (!opt_gid && !opt_nogid) opt_gid = gid_alloc (&gid, uid); fixgroups (newuid != uid, uid, opt_gid, gid); if (opt_U) sfs_setlogin (newuid); if (setgid (getgid ()) < 0 || setuid (newuid) < 0) fatal ("setuid/setgid: %m\n"); vec<char *> av; char *path = argc > 0 ? argv[0] : getenv ("SHELL"); if (!path) fatal ("no SHELL environment variable\n"); av.push_back (path); for (int i = 1; i < argc; i++) av.push_back (argv[i]); av.push_back (NULL); str av0; if (opt_login) { const char *p = strrchr (path, '/'); p = p ? p + 1 : path; av0 = strbuf ("-%s", p); av[0] = const_cast<char *> (av0.cstr ()); } if (opt_chdir) { if (chdir (opt_chdir) < 0) warn << opt_chdir << ": " << strerror (errno) << "\n"; else if (opt_chdir[0] == '/') { str e (strbuf ("PWD=%s", opt_chdir.cstr ())); xputenv (e); } else if (const char *p = getenv ("PWD")) { str e (strbuf ("PWD=%s/%s", p, opt_chdir.cstr ())); xputenv (e); } } str aidvar (strbuf ("SFS_AID=") << myaid ()); xputenv (aidvar); /* The SFS libraries use asynchronous IO which some programs don't * like. Thus, we remove the O_NONBLOCK flag from stdin/stdout. */ make_sync (0); make_sync (1); execvp (path, av.base ()); warnx ("%s: %m\n", path); return 1; }