static bool userinfo2str (strbuf &sb, const sfsauth_userinfo *ui) { str audit = single_char_sub (ui->audit, ':', "."); if (!namerx.match (ui->name) || (ui->owner && !namerx.match (*ui->owner)) || !nobadrx.match (ui->privs) || badcharrx.search (ui->pwauth) || badcharrx.search (audit)) return false; sb << ui->name; sb.fmt (":%u:%u:%u:", ui->id, ui->vers, ui->gid); if (ui->owner) sb << *ui->owner; sb << ":"; ptr<sfspub> pk = sfscrypt.alloc (ui->pubkey); if (!pk) return false; pk->export_pubkey (sb); sb << ":" << ui->privs << ":" << ui->pwauth << ":"; str priv = str2wstr (armor64 (ui->privkey.base (), ui->privkey.size())); sb << priv << ":"; sfs_2schnorr_priv::export_keyhalf (ui->srvprivkey, sb); // sb << ":" << ui->refresh << ":" << ui->timeout; sb << ":" << audit; return true; }
static void collect_pound_def (str s) { static rxx x ("#\\s*define\\s*(\\S+)\\s+(.*)"); if (guess_defines && x.match (s)) { collect_constant (x[1], "RPC_CONSTANT_POUND_DEF"); } }
static bool is_builtin(const str &s) { static rxx x ("(((unsigned|long|const)\\s+)*|(u_?)?)" "(bool|char|int|short|quad|long|" "int(8|16|32|64)_t)"); return x.match (s); }
bool cgi_mpfd_t::match (const http_inhdr_t &hdr, str *bndry) { if (multipart_rxx.match (hdr["content-type"])) { *bndry = multipart_rxx[1]; return true; } return false; }
bool pri2del (sfsauth_dbrec *dbrp, str aek) { static rxx userrx ("^USER:([^:])$"); static rxx grouprx ("^GROUP:([^:])$"); if (userrx.match (aek)) { dbrp->set_type (SFSAUTH_DELUSER); *dbrp->deleted = userrx[1]; } else if (grouprx.match (aek)) { dbrp->set_type (SFSAUTH_DELGROUP); *dbrp->deleted = grouprx[1]; } else { dbrp->set_type (SFSAUTH_ERROR); *dbrp->errmsg = strbuf () << "illegal deleted DB key " << aek; return false; } return true; }
bool sfsgroupmgr::parsegroup (str group, str *gname, str *ghost) { static rxx grouphostrx ("([A-Za-z][\\-\\w\\.]{0,31})(@[A-Za-z].+)?"); if (!grouphostrx.match (group)) { warn << "Could not parse group[@host]: " << group << "\n"; return false; } *gname = grouphostrx[1]; *ghost = grouphostrx[2] ? grouphostrx[2].cstr () : "-"; return true; }
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 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; }
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; }
bool groupinfo2str (strbuf &sb, const sfsauth_groupinfo *gi) { str audit = single_char_sub (gi->audit, ':', "."); if (!namerx.match (gi->name) || badcharrx.search (audit) || !nobadrx.match (gi->properties)) return false; sb << gi->name; sb.fmt (":%u:%u:", gi->id, gi->vers); if (!printlist (sb, gi->owners, printmember)) return false; sb << ":"; if (!printlist (sb, gi->members, printmember)) return false; // sb << ":" << gi->refresh << ":" << gi->timeout; sb << ":" << gi->properties; sb << ":" << audit; return true; }
sfs_connect_t * sfs_connect_srp (str u, srp_client *srpp, sfs_connect_cb cb, str *userp, str *pwdp, bool *serverokp) { static rxx usrhost ("^([^@]+)?@(.*)$"); if (!usrhost.match (u)) { if (userp) *userp = u; (*cb) (NULL, "not of form [user]@hostname"); return NULL; } str user (usrhost[1]), host (usrhost[2]); if (!user && !(user = myusername ())) { (*cb) (NULL, "could not get local username"); return NULL; } ref<sfssrp_authorizer> a (New refcounted<sfssrp_authorizer>); a->srpc = srpp; sfs_connect_t *cs = New sfs_connect_t (wrap (sfs_connect_srp_2, sfs::bundle_t<ref<sfssrp_authorizer>, str *, str *> (a, userp, pwdp), serverokp, cb)); cs->sname () = host; cs->service () = SFS_AUTHSERV; cs->encrypt = true; cs->check_hostid = false; cs->authorizer = a; cs->aarg.user = user; if (!cs->start ()) return NULL; return cs; }
bool nameok (const str &name) { static rxx namerx ("[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)*"); return name.len () < NFS_MAXNAMLEN && namerx.match (name); }
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 (); }
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 cgi_mpfd_t::parse_guts () { abuf_stat_t r = ABUF_OK; str dummy; bool inc; while (r == ABUF_OK) { OKDBG4(SVC_MPFD, CHATTER, "cgi_mpfd_t::parse_guts loop " "r=%d, state=%d", int (r), int (state)); inc = true; switch (state) { case MPFD_START: r = match_boundary (); break; case MPFD_EOL0: r = require_crlf (); break; case MPFD_KEY: r = gobble_crlf (); if (r == ABUF_OK) { if (to_start) { state = MPFD_START; to_start = false; } else state = MPFD_SEARCH; inc = false; } else if (r == ABUF_NOMATCH) { r = delimit_key (&mpfd_key); if (r == ABUF_OK) kt = mpfd_ktmap.lookup (mpfd_key); } // else a WAIT or an EOF in gobble_crlf break; case MPFD_SPC: r = abuf->skip_hws (1); cdp.reset (); break; case MPFD_VALUE: if (kt == MPFD_DISPOSITION) { OKDBG3(SVC_MPFD, CHATTER, "cgi_mpfd_t::parse_guts branch to nested " "content disposition parser"); cdp.parse (wrap (this, &cgi_mpfd_t::ext_parse_cb)); OKDBG3(SVC_MPFD, CHATTER, "cgi_mpfd_t::parse_guts return due to " "content disposition parser"); return; } else if (kt == MPFD_TYPE) { r = delimit_val (&content_typ); if (r == ABUF_OK) { if (multipart_rxx.match (content_typ)) { add_boundary (multipart_rxx[1]); to_start = true; } } } else { r = delimit_val (&dummy); } break; case MPFD_EOL1A: r = require_crlf (); break; case MPFD_EOL1B: if (kt == MPFD_DISPOSITION) { if (cdp.typ == CONTDISP_FORMDAT) { cgi_key = cdp.name; filename = cdp.filename; attach = filename; } else if (cdp.typ == CONTDISP_ATTACH) { filename = cdp.filename; attach = true; } else { r = ABUF_PARSE_ERR; } } state = MPFD_KEY; inc = false; break; case MPFD_SEARCH: r = match_boundary (&dat); if (r == ABUF_OK) { if (cgi_key) { if (attach) finsert (cgi_key, cgi_file_t (filename, content_typ, dat)); else insert (cgi_key, dat); cgi_key = NULL; } // in this case, no more boundaries } else if (r == ABUF_PARSE_ERR) { r = ABUF_OK; state = MPFD_EOF; inc = false; } break; case MPFD_SEARCH2: r = parse_2dash (); if (r == ABUF_OK) { remove_boundary (); nxt_state = MPFD_SEARCH; } else if (r == ABUF_NOMATCH) { r = ABUF_OK; nxt_state = MPFD_KEY; } break; case MPFD_SEARCH3: r = require_crlf (); if (r == ABUF_OK) { state = nxt_state; inc = false; } break; case MPFD_EOF: r = abuf->skip_ws (); break; default: break; } if (r == ABUF_OK && inc) MPFD_INC_STATE; } OKDBG4(SVC_MPFD, CHATTER, "cgi_mpfd_t::parse_guts exit loop " "r=%d, state=%d", int (r), int (state)); switch (r) { case ABUF_EOF: int rc; if (state == MPFD_EOF) { rc = HTTP_OK; } else { rc = HTTP_UNEXPECTED_EOF; warn ("mpfd EOF in state %d after %d bytes read\n", int (state), abuf ? abuf->get_ccnt () : -1); } finish_parse (rc); break; case ABUF_PARSE_ERR: finish_parse (HTTP_BAD_REQUEST); break; default: break; } }