/*
** @(#) 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 <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <9p.h>
#include <ber.h>
#include <oid.h>
#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;
}
|