/* ** @(#) sample.c - RDP development module ** @(#) $Id: b.c,v 1.4 2003/12/08 07:13:53 lucio Exp $ */ /* ** ================================================================== ** ** $Logfile:$ ** $RCSfile: b.c,v $ ** $Revision: 1.4 $ ** $Date: 2003/12/08 07:13:53 $ ** $Author: lucio $ ** ** ================================================================== ** ** $Log: b.c,v $ ** Revision 1.4 2003/12/08 07:13:53 lucio ** Weekend developments - mostly OID related ** ** Revision 1.3 2003/12/05 16:00:43 lucio ** Checkpoint - with a view to some homework. ** ** Revision 1.2 2003/11/11 05:03:33 lucio ** .cvsignore - too many complaints otherwise. ** ** Revision 1.1.1.1 2003/11/10 10:33:59 lucio ** ASN.1 developments. ** ** ================================================================== */ #include #include #include #include #include #include <9p.h> #include #include #define FILESZ (65535) #define NAMELEN (40) #define MSGLEN (80) static int objdup = 0; static OidHier *hierarchy; static char *ident = "@(#) $Id: b.c,v 1.4 2003/12/08 07:13:53 lucio Exp $"; static void copyright (char *prog) { print ("%s: BER test bench\n", prog); print ("Copyright (C) 2003 Lucio De Re.\n"); } static char *use[] = { "usage: %s [-h|H] [-v] [-N] [-m mtpt] [-p srv] [file]\n", "\n", "opts: -h|H: this message\n", " -v: noisy\n", " -N: show copyright notice\n", " -m mtpt: mountpoint (default /net/iso)\n", " -p srv: service name\n", "\n", " file: input data\n", nil }; static void usage (char *prog, char *use) { fprint (2, use, prog); exits ("usage"); } static void help (char *prog, char **use) { print (*use++, prog); while (*use) { print (*use++); } } static char *PEM_DATA_OBJECTID; static int LEN_PEM_DATA; static char *PEM_SIGNEDDATA_OBJECTID; static int LEN_PEM_SIGNEDDATA; static void objopen (Req *r); static void objread (Req *r); static void objwrite (Req *r); static void objclose (Req *r); static void objterm (Srv *s); static Tree *obj; static char *EAgain = "Not available, may be transient"; static Srv objsrv = { .open = objopen, .read = objread, .write = objwrite, .remove = objclose, .end = objterm, }; enum qtype { Qroot, Qobj, Qdata, }; typedef struct root root; struct root { int count; char *owner; File *root; }; typedef struct object object; struct object { int type; // file type identifier object *dir; // pointer to directory union { struct { // stats, ctl int ndata; char *data; }; struct { // dir long inbytes; long outbytes; }; struct { // data int fd; // channel long len, lsz; char *lbuf; }; }; }; OidHier *oid_ident (OidHier *h, char *id); char *ber_proid (BerObj *id); void objids (BerObj *op, int depth) { BerObj *opd; char *id; if (!op) return; if (opd = op->down) { // constructed record if (op->id) { print ("%*s tag = %d - len = %d - size = %d - OID = ", depth * 4, "", op->tag, op->len, op->size); id = ber_proid (op->id); print ("%s => %s\n", id, oid_ident (hierarchy, id)->name); } objids (opd, ++depth); while (opd = opd->next) { objids (opd, depth); } } return; } static void objopen (Req *r) { object *ff = (object *)(r->fid->file->aux); char msg[MSGLEN]; switch (ff->type) { case Qroot: // root node case Qobj: // object node break; case Qdata: // data file break; default: snprint (msg, MSGLEN, "File of type: %d", ff->type); respond (r, msg); return; } respond (r, nil); return; } static void objread (Req *r) { // vlong offset = r->ifcall.offset; long count = r->ifcall.count; char msg[MSGLEN]; object *ff = (object *)(r->fid->file->aux); // object *df = ff->dir; // int fd = df->fd; switch (ff->type) { case Qroot: // root node case Qobj: // object node break; case Qdata: // data file if (ff->len < count) count = ff->len; memcpy (r->ofcall.data, ff->lbuf, count); if ((ff->len -= count) > 0) memmove (ff->lbuf, ff->lbuf + count, ff->len); r->ofcall.count = count; ff->inbytes += count; break; default: snprint (msg, MSGLEN, "File of type: %d", ff->type); respond (r, msg); return; } respond (r, nil); return; } static void objwrite (Req *r) { respond (r, nil); return; } static void objclose (Req *r) { object *ff = (object *)(r->fid->file->aux); switch (ff->type) { default: respond (r, "close not implemented"); return; } respond (r, nil); return; } static void objterm (Srv *) { return; } static void objdest (File *) { return; } static void init (void) { BerObj *op; hierarchy = oid_initdb (nil); /* // data OBJECT IDENTIFIER op = ber_objid ("1.2.840.113549.1.7.1"); // iso.member-body.US.rsadsi.pkcs.pkcs-7.1 PEM_DATA_OBJECTID = malloc (LEN_PEM_DATA = op->len); memcpy (PEM_DATA_OBJECTID, op->buf, op->len); ber_free (op); // signedData OBJECT IDENTIFIER op = ber_objid ("1.2.840.113549.1.7.2"); // iso.member-body.US.rsadsi.pkcs.pkcs-7.2 PEM_SIGNEDDATA_OBJECTID = malloc (LEN_PEM_SIGNEDDATA = op->len); memcpy (PEM_SIGNEDDATA_OBJECTID, op->buf, op->len); ber_free (op); */ } void buildfs (File *root, BerObj *op, char *user, int skip) { BerObj *opd; char objname[BERSZ]; File *dd, *fd = root; OidObj aug; if (!op) return; if (opd = op->down) { if (op->id) { snprint (objname, BERSZ, "%O", op->id); // aug.obj = op; // aug.hier = hierarchy; // print ("\tObjname: %N\n", &aug); print ("%*s = (%s)/%s\n", skip * 4, "OBJ", (char *)(((object *)(fd->aux))->data), objname); hierarchy = oid_append (hierarchy, op->id, "unidentified", "", nil); fd = createfile (root, objname, user, DMDIR|0555, nil); if (!fd) { snprint (objname, BERSZ, "%O.dup.%d", op->id, ++objdup); fd = createfile (root, objname, user, DMDIR|0555, nil); if (!fd) sysfatal ("%s: %r", objname); } } else { snprint (objname, BERSZ, "%d", ++objdup); fd = createfile (root, objname, user, DMDIR|0555, nil); if (!fd) { snprint (objname, BERSZ, "node.dup.%d", ++objdup); fd = createfile (root, objname, user, DMDIR|0555, nil); if (!fd) sysfatal ("%s: %r", objname); } } fd->aux = emalloc9p (sizeof (object)); ((object *)(fd->aux))->type = Qobj; ++skip; buildfs (fd, opd, user, skip); while (opd = opd->next) { buildfs (fd, opd, user, skip); } } else { snprint (objname, BERSZ, "obj.%d", ++objdup); dd = createfile (root, objname, user, 0444, nil); dd->aux = emalloc9p (sizeof (object)); ((object *)(dd->aux))->type = Qdata; ((object *)(dd->aux))->lbuf = malloc (op->len); memcpy (((object *)(dd->aux))->lbuf, op->buf, op->len); ((object *)(dd->aux))->lsz = ((object *)(dd->aux))->len = op->len; } return; } void buildhier (BerObj *op) { BerObj *opd; char objname[BERSZ]; if (!op) return; if (opd = op->down) { if (op->id) { snprint (objname, BERSZ, "%O", op->id); // print ("%s = (%s)/%s\n", "OBJ", (char *)(((object *)(fd->aux))->data), objname); print ("%s\n", objname); hierarchy = oid_append (hierarchy, op->id, "unidentified", "", nil); } buildhier (opd); while (opd = opd->next) { buildhier (opd); } } } int main (int argc, char *argv[]) { BerObj *o; uchar *buf, *bp; int fd = 0, s, s0, size; char *u, user[NAMELEN]; // char *srvpt = nil; // char *mtpt = "/net"; root *r; u = getuser (); if(u == nil) u = "none"; strncpy (user, u, NAMELEN - 1); user[NAMELEN - 1] = 0; ARGBEGIN { case 'm': // mtpt = EARGF (usage (argv0, use[0])); break; case 'p': // srvpt = EARGF (usage (argv0, use[0])); break; case 'N': copyright (argv0); exits (0); case 'v': chatty9p++; break; case 'h': case 'H': case '?': help (argv0, use); exits (0); default: usage (argv0, use[0]); } ARGEND; if (argc == 1) fd = open (argv[0], OREAD); s0 = size = FILESZ; buf = malloc (FILESZ); bp = buf; while ((s = read (fd, bp, s0)) == s0) { s0 = size; // print ("Adjust: %d -> %d\n", s0, size * 2); buf = realloc (buf, size *= 2); /* If buf gets too big, we may need to think about caching only the bit we need. But that really means restructuring the BER code. */ bp = buf + s0; } // print ("Read: %d chars, %#x %#x %#x %#x %#x...\n", s, buf[0], buf[1], buf[2], buf[3], buf[4]); init (); fmtinstall ('O', ber_fmtoid); fmtinstall ('N', oid_fmtdn); o = ber_parse (buf, bp + s); if (!o) { fprint (2, "No object.\n"); exits ("no object"); } /* obj = alloctree (user, user, DMDIR|0555, objdest); // Tree if (!obj) { fprint (2, "No tree.\n"); exits ("no tree"); } obj->root->aux = emalloc9p (sizeof (object)); // root object ((object *)(obj->root->aux))->type = Qroot; // objsrv.tree = obj; objsrv.aux = emalloc9p (sizeof (root)); // root entry r = (root *) objsrv.aux; r->owner = estrdup9p (user); // root owner r->count = 0; // root count (??) buildhier (o); oid_hdump (hierarchy); exits (0); */ if (o) { ber_print (o, 1); // ber_seal (o); ber_objs (o, 1); buildhier (o); objids (o, 1); // oid_hdump (hierarchy); /* if (o->id) { if (memcmp (o->id->buf, PEM_DATA_OBJECTID, LEN_PEM_DATA) == 0) { } else if (memcmp (o->id->buf, PEM_SIGNEDDATA_OBJECTID, LEN_PEM_SIGNEDDATA) == 0) { // ber_objs (o, 1); } } */ } // postmountsrv (&objsrv, srvpt, mtpt, MAFTER); return 0; }