Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include "cifs.h"

static Pkt *
tnthdr(Session *s, Share *sp, int cmd)
{
        Pkt *p;

        p = cifshdr(s, sp, SMB_COM_NT_TRANSACT);
        p->tbase = p8(p, 0);            /*  0  Max setup count to return */
        pl16(p, 0);                     /*  1  reserved */
        pl32(p, 0);                     /*  3  Total parameter count */
        pl32(p, 0);                     /*  7  Total data count */
        pl32(p, 64);                    /* 11  Max parameter count to return */
        pl32(p, (MTU - T2HDRLEN)-64);   /* 15  Max data count to return */
        pl32(p, 0);                     /* 19  Parameter count (in this buffer) */
        pl32(p, 0);                     /* 23  Offset to parameters (in this buffer) */
        pl32(p, 0);                     /* 27  Count of data  in this buffer */
        pl32(p, 0);                     /* 31  Offset to data in this buffer */
        p8(p, 1);                       /* 35  Count of setup words */
        pl16(p, cmd);                   /* 37  setup[0] */
        pl16(p, 0);                     /* padding ??!?!? */
        pbytes(p);
        return p;
}

static void
ptntparam(Pkt *p)
{
        uchar *pos = p->pos;
        assert(p->tbase != 0);

        p->pos = p->tbase +23;
        pl32(p, (pos - p->buf) - NBHDRLEN); /* param offset */

        p->tparam = p->pos = pos;
}

static void
ptntdata(Pkt *p)
{
        uchar *pos = p->pos;
        assert(p->tbase != 0);
        assert(p->tparam != 0);

        p->pos = p->tbase +3;
        pl32(p, pos - p->tparam);               /* total param count */

        p->pos = p->tbase +19;
        pl32(p, pos - p->tparam);               /* param count */

        p->pos = p->tbase +31;
        pl32(p, (pos - p->buf) - NBHDRLEN);     /* data offset */
        p->tdata = p->pos = pos;
}

static int
tntrpc(Pkt *p)
{
        int got;
        uchar *pos;
        assert(p->tbase != 0);
        assert(p->tdata != 0);

        pos = p->pos;

        p->pos = p->tbase +7;
        pl32(p, pos - p->tdata);                /* total data count */

        p->pos = p->tbase +27;
        pl32(p, pos - p->tdata);                /* data count */

        p->pos = pos;
        if((got = cifsrpc(p)) == -1)
                return -1;

        g8(p);                          /* Reserved */
        g8(p);                          /* Reserved */
        g8(p);                          /* Reserved */
        gl32(p);                        /* Total parameter count */
        gl32(p);                        /* Total data count */
        gl32(p);                        /* Parameter count in this buffer */
        p->tparam = p->buf +NBHDRLEN +gl32(p); /* Parameter offset */
        gl32(p);                        /* Parameter displacement */
        gl32(p);                        /* Data count (this buffer); */
        p->tdata = p->buf +NBHDRLEN +gl32(p); /* Data offset */
        gl32(p);                        /* Data displacement */
        g8(p);                          /* Setup count */
        gl16(p);                        /* padding ???  */

        return got;
}

static void
gtntparam(Pkt *p)
{
        p->pos = p->tparam;
}

static void
gtntdata(Pkt *p)
{
        p->pos = p->tdata;
}


int
TNTquerysecurity(Session *s, Share *sp, int fh, char **usid, char **gsid)
{
        Pkt *p;
        uchar *base;
        Fmt fmt, *f = &fmt;
        int n, i, off2owner, off2group;

        p = tnthdr(s, sp, NT_TRANSACT_QUERY_SECURITY_DESC);
        ptntparam(p);

        pl16(p, fh);            /* File handle */
        pl16(p, 0);             /* Reserved */
        pl32(p, QUERY_OWNER_SECURITY_INFORMATION |
                QUERY_GROUP_SECURITY_INFORMATION);

        ptntdata(p);

        if(tntrpc(p) == -1){
                free(p);
                return -1;
        }

        gtntdata(p);

        base = p->pos;
        gl16(p);                        /* revision */
        gl16(p);                        /* type */
        off2owner = gl32(p);            /* offset to owner */
        off2group = gl32(p);            /* offset to group */
        gl32(p);
        gl32(p);

        if(off2owner){
                p->pos = base +  off2owner;
                fmtstrinit(f);
                fmtprint(f, "S-%ud", g8(p));    /* revision */
                n = g8(p);                      /* num auth */
                fmtprint(f, "-%llud", gb48(p)); /* authority */
                for(i = 0; i < n; i++)
                        fmtprint(f, "-%ud", gl32(p));   /* sub-authorities */
                *usid = fmtstrflush(f);
        }

        if(off2group){
                p->pos = base +  off2group;
                fmtstrinit(f);
                fmtprint(f, "S-%ud", g8(p));    /* revision */
                n = g8(p);                      /* num auth */
                fmtprint(f, "-%llud", gb48(p)); /* authority */
                for(i = 0; i < n; i++)
                        fmtprint(f, "-%ud", gl32(p));   /* sub-authorities */
                *gsid = fmtstrflush(f);
        }
        free(p);
        return 0;
}