The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/devcap.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #include        "u.h"
    2 #include        "../port/lib.h"
    3 #include        "mem.h"
    4 #include        "dat.h"
    5 #include        "fns.h"
    6 #include        "../port/error.h"
    7 
    8 #include        <libsec.h>
    9 
   10 enum
   11 {
   12         Hashlen=        SHA1dlen,
   13         Maxhash=        256,
   14 };
   15 
   16 /*
   17  *  if a process knows cap->cap, it can change user
   18  *  to capabilty->user.
   19  */
   20 typedef struct Caphash  Caphash;
   21 struct Caphash
   22 {
   23         Caphash *next;
   24         char            hash[Hashlen];
   25         ulong           ticks;
   26 };
   27 
   28 struct
   29 {
   30         QLock;
   31         Caphash *first;
   32         int     nhash;
   33 } capalloc;
   34 
   35 enum
   36 {
   37         Qdir,
   38         Qhash,
   39         Quse,
   40 };
   41 
   42 /* caphash must be last */
   43 Dirtab capdir[] =
   44 {
   45         ".",            {Qdir,0,QTDIR}, 0,              DMDIR|0500,
   46         "capuse",       {Quse},         0,              0222,
   47         "caphash",      {Qhash},        0,              0200,
   48 };
   49 int ncapdir = nelem(capdir);
   50 
   51 static Chan*
   52 capattach(char *spec)
   53 {
   54         return devattach(L'¤', spec);
   55 }
   56 
   57 static Walkqid*
   58 capwalk(Chan *c, Chan *nc, char **name, int nname)
   59 {
   60         return devwalk(c, nc, name, nname, capdir, ncapdir, devgen);
   61 }
   62 
   63 static void
   64 capremove(Chan *c)
   65 {
   66         if(iseve() && c->qid.path == Qhash)
   67                 ncapdir = nelem(capdir)-1;
   68         else
   69                 error(Eperm);
   70 }
   71 
   72 
   73 static int
   74 capstat(Chan *c, uchar *db, int n)
   75 {
   76         return devstat(c, db, n, capdir, ncapdir, devgen);
   77 }
   78 
   79 /*
   80  *  if the stream doesn't exist, create it
   81  */
   82 static Chan*
   83 capopen(Chan *c, int omode)
   84 {
   85         if(c->qid.type & QTDIR){
   86                 if(omode != OREAD)
   87                         error(Ebadarg);
   88                 c->mode = omode;
   89                 c->flag |= COPEN;
   90                 c->offset = 0;
   91                 return c;
   92         }
   93 
   94         switch((ulong)c->qid.path){
   95         case Qhash:
   96                 if(!iseve())
   97                         error(Eperm);
   98                 break;
   99         }
  100 
  101         c->mode = openmode(omode);
  102         c->flag |= COPEN;
  103         c->offset = 0;
  104         return c;
  105 }
  106 
  107 /*
  108 static char*
  109 hashstr(uchar *hash)
  110 {
  111         static char buf[2*Hashlen+1];
  112         int i;
  113 
  114         for(i = 0; i < Hashlen; i++)
  115                 sprint(buf+2*i, "%2.2ux", hash[i]);
  116         buf[2*Hashlen] = 0;
  117         return buf;
  118 }
  119  */
  120 
  121 static Caphash*
  122 remcap(uchar *hash)
  123 {
  124         Caphash *t, **l;
  125 
  126         qlock(&capalloc);
  127 
  128         /* find the matching capability */
  129         for(l = &capalloc.first; *l != nil;){
  130                 t = *l;
  131                 if(memcmp(hash, t->hash, Hashlen) == 0)
  132                         break;
  133                 l = &t->next;
  134         }
  135         t = *l;
  136         if(t != nil){
  137                 capalloc.nhash--;
  138                 *l = t->next;
  139         }
  140         qunlock(&capalloc);
  141 
  142         return t;
  143 }
  144 
  145 /* add a capability, throwing out any old ones */
  146 static void
  147 addcap(uchar *hash)
  148 {
  149         Caphash *p, *t, **l;
  150 
  151         p = smalloc(sizeof *p);
  152         memmove(p->hash, hash, Hashlen);
  153         p->next = nil;
  154         p->ticks = m->ticks;
  155 
  156         qlock(&capalloc);
  157 
  158         /* trim extras */
  159         while(capalloc.nhash >= Maxhash){
  160                 t = capalloc.first;
  161                 if(t == nil)
  162                         panic("addcap");
  163                 capalloc.first = t->next;
  164                 free(t);
  165                 capalloc.nhash--;
  166         }
  167 
  168         /* add new one */
  169         for(l = &capalloc.first; *l != nil; l = &(*l)->next)
  170                 ;
  171         *l = p;
  172         capalloc.nhash++;
  173 
  174         qunlock(&capalloc);
  175 }
  176 
  177 static void
  178 capclose(Chan*)
  179 {
  180 }
  181 
  182 static long
  183 capread(Chan *c, void *va, long n, vlong)
  184 {
  185         switch((ulong)c->qid.path){
  186         case Qdir:
  187                 return devdirread(c, va, n, capdir, ncapdir, devgen);
  188 
  189         default:
  190                 error(Eperm);
  191                 break;
  192         }
  193         return n;
  194 }
  195 
  196 static long
  197 capwrite(Chan *c, void *va, long n, vlong)
  198 {
  199         Caphash *p;
  200         char *cp;
  201         uchar hash[Hashlen];
  202         char *key, *from, *to;
  203         char err[256];
  204 
  205         switch((ulong)c->qid.path){
  206         case Qhash:
  207                 if(!iseve())
  208                         error(Eperm);
  209                 if(n < Hashlen)
  210                         error(Eshort);
  211                 memmove(hash, va, Hashlen);
  212                 addcap(hash);
  213                 break;
  214 
  215         case Quse:
  216                 /* copy key to avoid a fault in hmac_xx */
  217                 cp = nil;
  218                 if(waserror()){
  219                         free(cp);
  220                         nexterror();
  221                 }
  222                 cp = smalloc(n+1);
  223                 memmove(cp, va, n);
  224                 cp[n] = 0;
  225 
  226                 from = cp;
  227                 key = strrchr(cp, '@');
  228                 if(key == nil)
  229                         error(Eshort);
  230                 *key++ = 0;
  231 
  232                 hmac_sha1((uchar*)from, strlen(from), (uchar*)key, strlen(key), hash, nil);
  233 
  234                 p = remcap(hash);
  235                 if(p == nil){
  236                         snprint(err, sizeof err, "invalid capability %s@%s", from, key);
  237                         error(err);
  238                 }
  239 
  240                 /* if a from user is supplied, make sure it matches */
  241                 to = strchr(from, '@');
  242                 if(to == nil){
  243                         to = from;
  244                 } else {
  245                         *to++ = 0;
  246                         if(strcmp(from, up->user) != 0)
  247                                 error("capability must match user");
  248                 }
  249 
  250                 /* set user id */
  251                 kstrdup(&up->user, to);
  252                 up->basepri = PriNormal;
  253 
  254                 free(p);
  255                 free(cp);
  256                 poperror();
  257                 break;
  258 
  259         default:
  260                 error(Eperm);
  261                 break;
  262         }
  263 
  264         return n;
  265 }
  266 
  267 Dev capdevtab = {
  268         L'¤',
  269         "cap",
  270 
  271         devreset,
  272         devinit,
  273         devshutdown,
  274         capattach,
  275         capwalk,
  276         capstat,
  277         capopen,
  278         devcreate,
  279         capclose,
  280         capread,
  281         devbread,
  282         capwrite,
  283         devbwrite,
  284         capremove,
  285         devwstat
  286 };

Cache object: bf3747d00eebda856605c05b87442b51


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.