Ejemplo n.º 1
0
Archivo: acl.C Proyecto: bougyman/sfs
u_int 
acl::get_permissions (sfsauth_cred *cred, str *key,
                      vec<sfs_idname> *groups)
{
  vec<str> credstrings;
  u_int p = 0;

  // 3 kinds of access: anonymous, public key, unix credentials
  // anonymous means that the user wasn't running an agent or
  // for some reason the authd couldn't even return a public key
  if (key)
    credstrings.push_back (strbuf () << TYPEPK << ACLDIV << *key); 
  if (cred)
    credstrings.push_back (strbuf () << TYPELOCALUSER << ACLDIV << cred->unixcred->username);
  if (groups) {
    for (unsigned int i = 0; i < groups->size (); i++)
      credstrings.push_back (strbuf () << TYPELOCALGROUP << ACLDIV << (*groups)[i]);
  }
  if (!cred && !key)
    credstrings.push_back (strbuf () << TYPESYS << ACLDIV << SYS_ANONYMOUS);

  str flattened_creds ("");
  for (u_int i = 0; i < credstrings.size (); i++) {
    warn ("CRED[%d]: %s\n", i, credstrings[i].cstr ());
    flattened_creds = strbuf () << flattened_creds << credstrings[i];
  }

#if PCACHE
  //make hash out of acl and user; ask cache about hash
  str ua = strbuf () << armor32 (str (aclhash, sizeof (aclhash)))
		     << flattened_creds;
  bzero (hashbuf, sizeof (hashbuf));
  sha1_hash (hashbuf, ua.cstr (), ua.len ());

  if (is_cached (hashbuf, p)) {
    warn << "Using cached perms (" << get_strpermissions (p)
      << ") for cache key "<< armor32 (str (hashbuf, sizeof (hashbuf)))
      << "\n";
    return p;
  } 
  else {
    warn << "Did not find cached perms (" << ua << ") for cache key "
      << armor32 (str (hashbuf, sizeof (hashbuf))) << "\n";
  }
#endif

  p = parse_acl (credstrings);

#if PCACHE
  insert_cache (hashbuf, p);
#endif

  return p;
}
Ejemplo n.º 2
0
Archivo: acl.C Proyecto: bougyman/sfs
void
acl::insert_cache (const char *u, u_int p)
{
  lastpos = (lastpos + 1) % PCACHESIZE;
  if (pcache[lastpos].set (u, p)) {
#if ACL_CACHETEST
    warn << "Inserting cache permissions for key "
      << armor32 (str (u, sizeof (hashbuf))) 
      << "\nat cache position " << lastpos << "\n";
#endif
  } else
    warn << "Failed to cache permissions for key " 
      << armor32 (str (u, sizeof (hashbuf))) << "\n";
}
inline str
arg2user (const sfs_autharg2 &aa)
{
  str user;
  switch (aa.type) {
  case SFS_AUTHREQ2:
    user = aa.sigauth->req.user;
    break;
  case SFS_UNIXPWAUTH:
    user = aa.pwauth->req.user;
    break;
  case SFS_SRPAUTH:
    user = aa.srpauth->req.user;
    break;
  default:
    user = "";
    break;
  }

  for (const char *p = user; *p; p++)
    if (*p <= ' ' || *p >= 127) {
      user = "";
      break;
    }
  if (user.len ())
    return user;

  switch (aa.type) {
  case SFS_AUTHREQ:
    if (ptr<sfspub> pk = sfscrypt.alloc (aa.authreq1->usrkey))
      user = strbuf ("keyhash ") << armor32 (pk->get_pubkey_hash ());
    break;
  case SFS_AUTHREQ2:
    if (ptr<sfspub> pk = sfscrypt.alloc (aa.sigauth->key))
      user = strbuf ("keyhash ") << armor32 (pk->get_pubkey_hash ());
    break;
  default:
    break;
  }

  if (!user || !user.len ())
    user = "******";
  return user;
}
Ejemplo n.º 4
0
Archivo: acl.C Proyecto: bougyman/sfs
bool
pcache_entry::set (const char *h, u_int p)
{
  //copy h -> hashbuf
  bzero (hashbuf, sizeof (hashbuf));
  memcpy (hashbuf, h, sizeof (hashbuf));
  warn << "Setting cache entry perms (" 
       << get_strpermissions (p) << ") for key "
       << armor32 (str (h, sizeof (hashbuf))) << "\n";
  perms = p;
  key_set = true;
  return true; 
}
static void
sclone (ref<asrv> s, ref<axprt_clone> x, sockaddr_in sin, svccb *sbp)
{
  s->setcb (NULL);
  if (!sbp) {
    warn ("invalid connect from %s\n", inet_ntoa (sin.sin_addr));
    return;
  }
  if (sbp->proc () != SFSPROC_CONNECT) {
    sbp->reject (PROC_UNAVAIL);
    return;
  }

  sfs_connectarg *arg = sbp->Xtmpl getarg<sfs_connectarg> ();
  u_int32_t rel;
  sfs_service service;
  str name;
  sfs_hash hostid;
  rpc_vec<sfs_extension, RPC_INFINITY> *extensions;

  switch (arg->civers) {
  case 4:
    rel = 4;
    service = arg->ci4->service;
    name = arg->ci4->name;
    hostid = arg->ci4->hostid;
    extensions = &arg->ci4->extensions;
    break;
  case 5:
    rel = arg->ci5->release;
    service = arg->ci5->service;
    if (!sfs_parsepath (arg->ci5->sname, &name, &hostid))
      name = arg->ci5->sname;
    extensions = &arg->ci5->extensions;
    break;
  default:
    sbp->reject (GARBAGE_ARGS);
    return;
  }

  bhash<str> eh;
  for (const sfs_extension *ep = extensions->base ();
       ep < extensions->lim (); ep++)
    eh.insert (*ep);

  sfs_pathrevoke cert;
  str rawcert = file2str (revocationdir << "/" << 
			  armor32 (hostid.base (), hostid.size ()));
  if (rawcert && str2xdr (cert, rawcert)) {
    sfs_connectres res(SFS_REDIRECT);
    res.revoke->msg = cert.msg;
    res.revoke->sig = cert.sig;
    sbp->reply (&res);
    return;
  }

  const char *source = inet_ntoa (sin.sin_addr);

  server *srv;
  for (srv = serverlist.first; srv; srv = serverlist.next (srv))
    if (srv->host == name && srv->hostid && *srv->hostid == hostid)
      if (srv->clone (x, sbp, source, rel, service, eh))
	return;
      else
	break;
  for (srv = serverlist.first; srv; srv = serverlist.next (srv))
    if (srv->host == name && !srv->hostid)
      if (srv->clone (x, sbp, source, rel, service, eh))
	return;
      else
	break;
  for (srv = serverlist.first; srv; srv = serverlist.next (srv))
    if (srv->host == name)
      if (srv->clone (x, sbp, source, rel, service, eh))
	return;
  for (srv = serverlist.first; srv; srv = serverlist.next (srv))
    if (srv->clone (x, sbp, source, rel, service, eh))
      return;
  sbp->replyref (sfs_connectres (SFS_NOSUCHHOST));
}
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);
}