예제 #1
0
파일: sfsconst.C 프로젝트: okws/sfslite
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 ();
}
예제 #2
0
파일: tst2d.C 프로젝트: Y317608039/okws
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;
}
예제 #5
0
파일: pt1cli.C 프로젝트: LeadsPlus/okws
  // 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;
  }
예제 #6
0
파일: ex4m.C 프로젝트: gildafnai82/craq
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 ();
}
예제 #7
0
파일: sfskey2edit.C 프로젝트: bougyman/sfs
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 ();
}
예제 #8
0
파일: sfsconst.C 프로젝트: okws/sfslite
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;
}
예제 #9
0
파일: sfskey.C 프로젝트: bougyman/sfs
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 ();
}
예제 #10
0
파일: pubutil.C 프로젝트: Y317608039/okws
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;
}
예제 #12
0
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)));
    }
  }
}
예제 #13
0
파일: degz.C 프로젝트: Keloran/okws
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;
}
예제 #15
0
파일: dsdc_util.C 프로젝트: okws/dsdc
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;
}
예제 #16
0
파일: xfer.C 프로젝트: bougyman/sfs
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;
}
예제 #17
0
파일: mtdispatch.C 프로젝트: Keloran/okws
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;
}
예제 #19
0
파일: sfsconst.C 프로젝트: okws/sfslite
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;
}
예제 #20
0
파일: sfskeygroup.C 프로젝트: bougyman/sfs
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 ();
  }
}
예제 #21
0
파일: pt1cli.C 프로젝트: LeadsPlus/okws
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);
  }
}
예제 #22
0
파일: pt1cli.C 프로젝트: LeadsPlus/okws
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 ();
}
예제 #23
0
파일: aiod.C 프로젝트: bougyman/sfs
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;
}
예제 #24
0
파일: regress.C 프로젝트: bougyman/sfs
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;
}
예제 #28
0
파일: sfsconst.C 프로젝트: okws/sfslite
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);
}
예제 #30
0
파일: newaid.C 프로젝트: bougyman/sfs
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;
}