Plan 9 from Bell Labs’s /usr/web/sources/contrib/lucio/asn1/devel/b.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
**	@(#) 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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].