diff --git a/sys/include/libc.h b/sys/include/libc.h index 521e24b8b..7f1bb83fe 100644 --- a/sys/include/libc.h +++ b/sys/include/libc.h @@ -536,7 +536,6 @@ extern int reject(int, char*, char*); /* * encryption */ -extern int pushssl(int, char*, char*, char*, int*); extern int pushtls(int, char*, char*, int, char*, char*); /* diff --git a/sys/man/1/cpu b/sys/man/1/cpu index 41b60a015..e69de29bb 100644 --- a/sys/man/1/cpu +++ b/sys/man/1/cpu @@ -1,237 +0,0 @@ -.TH CPU 1 -.SH NAME -cpu \- connection to CPU server -.SH SYNOPSIS -.B cpu -[ -.B -p -] [ -.B -h -.I server -] [ -.B -u -.I user -] [ -.B -a -.I auth-method -] [ -.B -P -.I patternfile -] [ -.B -e -.I encryption-hash-algs -] [ -.B -k -.I keypattern -] [ -.B -c -.I cmd args ... -] -.PP -.B cpu -[ -.B -n -] [ -.B -A -.I address -] [ -.B -R -] -.SH DESCRIPTION -This tool is deprecated and has been replaced by -.IR rcpu (1). -.PP -.I Cpu -starts an -.IR rc (1) -running on the -.I server -machine, or the machine named in the -.B $cpu -environment variable if there is no -.B -h -option. -.IR Rc 's -standard input, output, and error files will be -.B /dev/cons -in the name space where the -.I cpu -command was invoked. -Normally, -.I cpu -is run in an -.IR rio (1) -window on a terminal, so -.IR rc -output goes to that window, and input comes from the keyboard -when that window is current. -.IR Rc 's -current directory is -the working directory of the -.I cpu -command itself. -.PP -The name space for the new -.I rc -is an analogue of the name space where the -.I cpu -command was invoked: -it is the same except for architecture-dependent bindings such as -.B /bin -and the use of fast paths to file servers, if available. -.PP -If a -.B -u -argument is present, -.I cpu -uses the argument as the remote user id. -.PP -If a -.B -c -argument is present, the remainder of the command line is executed by -.I rc -on the server, and then -.I cpu -exits. -.PP -If a -.B -P -argument is present, the -.I patternfile -is passed to -.IR oexportfs (4) -to control how much of the local name space will be exported to -the remote system. -.PP -The -.B -a -command allows the user to specify the authentication mechanism used -when connecting to the remote system. The two possibilities for -.I auth-method -are: -.TF netkey -.TP -.B p9 -This is the default. Authentication is done using the standard Plan 9 -mechanisms, (see -.IR authsrv (6)). -No user interaction is required. -.TP -.B netkey -Authentication is done using challenge/response and a hand held -authenticator or the -.I netkey -program -(see -.IR passwd (1)). -The user must encrypt the challenge and type the encryption -back to -.IR cpu . -This is used if the local host is in a different protection domain than -the server or if the user wants to log into the server as a different -user. -.TP -.B none -This skips authentication. This requires the -.IR -n -flag to be specified on the remote side. -.PD -.PP -The -.B -e -option specifies an encryption and/or hash algorithm to -use for the connection. If both are specified, they must -be space separated and comprise a single argument, so they -must be quoted if in a shell command. The default is -.L rc4_256 -encryption and -.L sha1 -hashing. See -.IR ssl (3) -for details on possible algorithms. The argument -.L clear -specifies no encryption algorithm and can be used to talk -to older versions of the -.I cpu -service. -.PP -The -.B -k -flag specifies a key pattern to use to restrict the keys -selected by the -.I auth_proxy -call used for authentication. -.PP -The name space is built by running -.B /usr/$user/lib/profile -with the root of the invoking name space bound to -.BR /mnt/term . -The -.B service -environment variable is set to -.BR cpu ; -the -.B cputype -and -.B objtype -environment variables reflect the server's architecture. -.PP -The -.B -R -flag causes -.I cpu -to run the server (remote) side of the protocol. -It is run from service files such as -.BR /bin/service/tcp17010 . -The -.B -n -option allows using the -.B none -authentication method for incoming connections and must be -specified before the -.B -R -flag. -.PP -The -.B -p -flag pushes the -.IR aan (8) -filter onto the connection to protect against temporary -network outages. -.PP -The -.B -A -flag sets the announce-string -.I address -to use for -.IR aan (8) -connections, if requested by the initial protocol. -.SH FILES -The name space of the terminal side of the -.I cpu -command is mounted, via -.IR oexportfs (4), -on the CPU side on directory -.BR /mnt/term . -The files such as -.B /dev/cons -are bound to their standard locations from there. -.SH SOURCE -.B /sys/src/cmd/cpu.c -.SH SEE ALSO -.IR rcpu (1) , -.IR rc (1) , -.IR rio (1) , -.IR oexportfs (4) , -.IR aan (8) -.SH BUGS -Binds and mounts done after the terminal -.B lib/profile -is run are not reflected in the new name space. -.PP -By default, the entire namespace of the local system is -exported to the remote system. Use of the -.B -P -option in conjunction with a customized patternfile can -limit this exposure, but also limits the usefulness of -.B /mnt/term. diff --git a/sys/man/4/import b/sys/man/4/import index 9c6511dfc..e69de29bb 100644 --- a/sys/man/4/import +++ b/sys/man/4/import @@ -1,221 +0,0 @@ -.TH IMPORT 4 -.SH NAME -import \- import a name space from a remote system -.SH SYNOPSIS -.B import -[ -.I options -] -.I system -.I file -[ -.I mountpoint -] -.PP -.B import -.B -B -[ -.I options -] -.I mountpoint -[ -.I cmd -[ -.I args ... -] -] -.SH DESCRIPTION -This tool is deprecated and has been replaced by -.I rimport -(see -.IR rcpu (1)). -.PP -.I Import -allows an arbitrary -.I file -on a remote -.I system -to be imported into the local name space. -Usually -.I file -is a directory, so the complete -file tree under the directory is made available. -.PP -A process is started on the -remote machine, with authority of the user of -.IR import , -to perform work for the local machine using the -.IR oexportfs (4) -service. -The default port used is TCP 17007. -If -.I mountpoint -is omitted -.I import -uses the name of the remote -.I file -as the local mount point. -.PP -The options are: -.TF "-s namexxx" -.PD -.TP -.B -a -b -c -C -Control the construction of union directories, as in -.I mount -and -.IR bind (1). -Only valid when -.I file -is a directory. -.TP -.B -A -Skip the authentication protocol. -This is useful for connecting to foreign systems like Inferno. -.TP -.B -z -Bypass the initial protocol request for which remote tree to serve. -This is necessary when the remote -.IR oexportfs (4) -is running with the -.B -r -or -.B -S -options which pre-select a file tree to serve. The exception is if both sides are -operating in the -.B -B -backwards mode. -.TP -.B -B -Run in ``backwards'' mode, described below. -.TP -.B -E \fIenc -Push an encryption protocol on its network connection. -The supported protocols are -.B clear -(the default, no protocol) -and -.BR ssl . -There are plans to make -.B tls -available. -.TP -.B -e '\fIenc hash\fR' -Specify the encryption and hash algorithms to use for -encrypting and authenticating the wire traffic -(see -.IR ssl (3)). -The defaults are -.B rc4_256 -and -.BR sha1 . -.TP -.B -k \fIkeypattern -Use -.I keypattern -to select a key to authenticate to the remote side -(see -.IR auth (2)). -.TP -.B -p -Push the -.IR aan (8) -filter onto the connection to protect against -temporary network outages. -.TP -.B -n -Specify announce string for -.IR aan (8) -filter when run in ``backwards'' mode. -.TP -.B -s \fIname -Post the connection's mountable file descriptor as -.BI /srv/ name\fR. -.PD -.PP -The -.B -B -option runs -.I import -in ``backwards'' mode. -In this mode, -.I import -runs a -.I p9any -authentication (as server) over its file descriptor 0 -(expected to be an incoming network connection from -.B oexportfs -.BR -B ), -mounts the connection onto -.IR mntpt , -and optionally runs -.I cmd -.IR args . -.SH EXAMPLES -Assume a machine -.B kremvax -that has IP interfaces for the company intranet and the global -internet mounted on -.I /net -and -.I /net.alt -respectively. -Any machine inside the company can get telnet out to the global -internet using: -.IP -.EX -import -a kremvax /net.alt -telnet /net.alt/tcp!ucbvax -.EE -.PP -Suppose that the machine -.B moscvax -has access to a private file server containing public web pages -that need to be served by the less-trusted server -.BR webvax . -.B Webvax -runs the following listener -(see -.IR listen (8)) -on TCP port 999: -.IP -.EX -#!/bin/rc -import -B -s rowebfs /usr/web /bin/restarthttpd -.EE -.PP -When -.B moscvax -boots, it runs -.IP -.EX -oexportfs -R -r /usr/web -B tcp!webvax!999 -.EE -.PP -to serve a read-only copy of -.B /usr/web -to -.BR webvax . -When -.B webvax -gets the call, -.B import -mounts the served tree onto its own -.B /usr/web -and then runs -.B /bin/restarthttpd -to restart -.IR httpd (8). -.SH SOURCE -.B /sys/src/cmd/import.c -.SH SEE ALSO -.IR rcpu (1), -.IR bind (1), -.IR ssl (3), -.IR oexportfs (4), -.IR srv (4), -.IR aan (8), -.IR listen (8), -.B cs -in -.IR ndb (8) diff --git a/sys/man/4/oexportfs b/sys/man/4/oexportfs index 64f156c09..e69de29bb 100644 --- a/sys/man/4/oexportfs +++ b/sys/man/4/oexportfs @@ -1,143 +0,0 @@ -.TH OEXPORTFS 4 -.SH NAME -oexportfs \- legacy exportfs for cpu and import -.SH SYNOPSIS -.PP -.B oexportfs -[ -.I options -] -.SH DESCRIPTION -.I Oexportfs -is older version of the -.IR exportfs (4) -program that handles an initial protocol to establish a root directory -for the exported name space. -It also provides authentication and encryption using -the -.IR ssl (3) -device. -.PP -It is used exclusively by the deprecated -.IR cpu (1) -and -.IR import (4) -services. -.PP -The options are: -.TP -.B -d -Log all 9P traffic to standard error. -.TP -.B -P \fIpatternfile -Restrict the set of exported files. -.I Patternfile -contains one regular expression per line, -to be matched against path names -relative to the current working directory -and starting with -.BR / . -For a file to be exported, all lines with a prefix -.B + -must match and all those with prefix -.B - -must not match. -.TP -.B -R -Make the served name space read only. -.TP -.B -r \fIroot -Serve the name space rooted at -.IR root . -.TP -.B -S \fIservice -Serve the result of mounting -.IR service . -A separate mount is used for each -.IR attach (5) -message, -to correctly handle servers in which each mount -corresponds to a different client -.IR e.g. , ( -.IR rio (4)). -.TP -.B -s -equivalent to -.B -r -.BR / ; -kept for compatibility. -.TP -.B -m \fImsize -Set the maximum message size that -.I oexportfs -should offer to send (see -.IR version (5)); -this helps tunneled -9P connections to avoid unnecessary fragmentation. -.TP -.B -A \fIaddress -Use the network -.I address -to announce -.IR aan (8) -connections, -if requested by the initial protocol. -.TP -.B -a -Authenticate the user with the -.I p9any -protocol before running the regular -.I oexportfs -session; used when -.I oexportfs -is invoked to handle an incoming network connection. -.I Exportfs -creates a new name space for each connection, using -.B /lib/namespace -by default (see -.IR namespace (6)). -.TP -.B -B \fIaddress -Dial -.IR address , -authenticate as a -.I p9any -client, and then -serve that network connection. -Requires setting the root of the name space with -.B -r -or -.BR -s . -The remote system should run -.B import -.B -B -to handle the call. -See -.IR import (4) -for an example. -.TP -.B -e '\fIenc auth\fL' -Set the encryption and authentication algorithms to use for -encrypting the wire traffic (see -.IR ssl (3)). -The defaults are -.B rc4_256 -and -.BR sha1 . -.TP -.B -N \fInsfile -Serve the name space described by -.IR nsfile . -.TP -.B -n -Disallow mounts by user -.BR none . -.EE -.SH SOURCE -.B /sys/src/cmd/exportfs/oexportfs.c -.SH SEE ALSO -.IR dial (2), -.IR exportfs (4), -.IR import (4), -.IR aan (8), -.IR listen (8) diff --git a/sys/src/9/bcm/pi b/sys/src/9/bcm/pi index 0ac4fdcea..600d92775 100644 --- a/sys/src/9/bcm/pi +++ b/sys/src/9/bcm/pi @@ -10,7 +10,6 @@ dev shr dup arch - ssl tls cap fs diff --git a/sys/src/9/bcm/pi2 b/sys/src/9/bcm/pi2 index ffa63f665..be1b01255 100644 --- a/sys/src/9/bcm/pi2 +++ b/sys/src/9/bcm/pi2 @@ -10,7 +10,6 @@ dev shr dup arch - ssl tls cap fs diff --git a/sys/src/9/bcm/picpuf b/sys/src/9/bcm/picpuf index 19620758c..a2966eff8 100644 --- a/sys/src/9/bcm/picpuf +++ b/sys/src/9/bcm/picpuf @@ -10,7 +10,6 @@ dev shr dup arch - ssl tls cap fs diff --git a/sys/src/9/bcm64/pi3 b/sys/src/9/bcm64/pi3 index e81794b69..8cc817106 100644 --- a/sys/src/9/bcm64/pi3 +++ b/sys/src/9/bcm64/pi3 @@ -10,7 +10,6 @@ dev shr dup arch - ssl tls cap fs diff --git a/sys/src/9/bcm64/pi4 b/sys/src/9/bcm64/pi4 index 2bd10a1ea..61c7602b8 100644 --- a/sys/src/9/bcm64/pi4 +++ b/sys/src/9/bcm64/pi4 @@ -10,7 +10,6 @@ dev shr dup arch - ssl tls cap fs diff --git a/sys/src/9/cycv/cycv b/sys/src/9/cycv/cycv index 7883a6575..d2fd41246 100644 --- a/sys/src/9/cycv/cycv +++ b/sys/src/9/cycv/cycv @@ -13,7 +13,6 @@ dev dup ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno - ssl tls # cap # kprof diff --git a/sys/src/9/kw/plug b/sys/src/9/kw/plug index 320941ae7..9ce9bc9bf 100644 --- a/sys/src/9/kw/plug +++ b/sys/src/9/kw/plug @@ -13,7 +13,6 @@ dev dup rtc arch - ssl tls cap kprof diff --git a/sys/src/9/mtx/mtx b/sys/src/9/mtx/mtx index ed1156209..30faf21b9 100644 --- a/sys/src/9/mtx/mtx +++ b/sys/src/9/mtx/mtx @@ -10,7 +10,6 @@ dev mnt srv dup - ssl cap kprof uart diff --git a/sys/src/9/omap/beagle b/sys/src/9/omap/beagle index 99b69005f..e52680186 100644 --- a/sys/src/9/omap/beagle +++ b/sys/src/9/omap/beagle @@ -11,7 +11,6 @@ dev shr dup arch - ssl tls bridge log sdp thwack unthwack diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index 9d980f903..2cacee652 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -13,7 +13,6 @@ dev shr dup rtc - ssl tls cap kprof diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index 1c9fbd172..bafda3d72 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -13,7 +13,6 @@ dev shr dup rtc - ssl tls cap kprof diff --git a/sys/src/9/port/devssl.c b/sys/src/9/port/devssl.c index d48ba5d1e..e69de29bb 100644 --- a/sys/src/9/port/devssl.c +++ b/sys/src/9/port/devssl.c @@ -1,1462 +0,0 @@ -/* - * devssl - secure sockets layer - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#include - -#define NOSPOOKS 1 - -typedef struct OneWay OneWay; -struct OneWay -{ - QLock q; - QLock ctlq; - - void *state; /* encryption state */ - int slen; /* hash data length */ - uchar *secret; /* secret */ - ulong mid; /* message id */ -}; - -enum -{ - /* connection states */ - Sincomplete= 0, - Sclear= 1, - Sencrypting= 2, - Sdigesting= 4, - Sdigenc= Sencrypting|Sdigesting, - - /* encryption algorithms */ - Noencryption= 0, - DESCBC= 1, - DESECB= 2, - RC4= 3 -}; - -typedef struct Dstate Dstate; -struct Dstate -{ - Chan *c; /* io channel */ - uchar state; /* state of connection */ - int ref; /* serialized by dslock for atomic destroy */ - - uchar encryptalg; /* encryption algorithm */ - ushort blocklen; /* blocking length */ - - ushort diglen; /* length of digest */ - DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); /* hash func */ - - /* for SSL format */ - int max; /* maximum unpadded data per msg */ - int maxpad; /* maximum padded data per msg */ - - /* input side */ - OneWay in; - Block *processed; - Block *unprocessed; - - /* output side */ - OneWay out; - - /* protections */ - char *user; - int perm; -}; - -enum -{ - Maxdmsg= 1<<16, - Maxdstate= 512, /* max. open ssl conn's; must be a power of 2 */ -}; - -static Lock dslock; -static int dshiwat; -static char *dsname[Maxdstate]; -static Dstate *dstate[Maxdstate]; -static char *encalgs; -static char *hashalgs; - -enum{ - Qtopdir = 1, /* top level directory */ - Qprotodir, - Qclonus, - Qconvdir, /* directory for a conversation */ - Qdata, - Qctl, - Qsecretin, - Qsecretout, - Qencalgs, - Qhashalgs, -}; - -#define TYPE(x) ((x).path & 0xf) -#define CONV(x) (((x).path >> 5)&(Maxdstate-1)) -#define QID(c, y) (((c)<<5) | (y)) - -static void ensure(Dstate*, Block**, int); -static void consume(Block**, uchar*, int); -static void setsecret(OneWay*, uchar*, int); -static Block* encryptb(Dstate*, Block*, int); -static Block* decryptb(Dstate*, Block*); -static Block* digestb(Dstate*, Block*, int); -static void checkdigestb(Dstate*, Block*); -static Chan* buftochan(char*); -static void sslhangup(Dstate*); -static Dstate* dsclone(Chan *c); -static void dsnew(Chan *c, Dstate **); -static long sslput(Dstate *s, Block * volatile b); - -char *sslnames[] = { -[Qclonus] "clone", -[Qdata] "data", -[Qctl] "ctl", -[Qsecretin] "secretin", -[Qsecretout] "secretout", -[Qencalgs] "encalgs", -[Qhashalgs] "hashalgs", -}; - -static int -sslgen(Chan *c, char*, Dirtab *d, int nd, int s, Dir *dp) -{ - Qid q; - Dstate *ds; - char name[16], *p, *nm; - int ft; - - USED(nd); - USED(d); - - q.type = QTFILE; - q.vers = 0; - - ft = TYPE(c->qid); - switch(ft) { - case Qtopdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, "#D", 0, eve, 0555, dp); - return 1; - } - if(s > 0) - return -1; - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "ssl", 0, eve, 0555, dp); - return 1; - case Qprotodir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qtopdir); - q.type = QTDIR; - devdir(c, q, ".", 0, eve, 0555, dp); - return 1; - } - if(s < dshiwat) { - q.path = QID(s, Qconvdir); - q.type = QTDIR; - ds = dstate[s]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - if(dsname[s] == nil){ - sprint(name, "%d", s); - kstrdup(&dsname[s], name); - } - devdir(c, q, dsname[s], 0, nm, 0555, dp); - return 1; - } - if(s > dshiwat) - return -1; - q.path = QID(0, Qclonus); - devdir(c, q, "clone", 0, eve, 0555, dp); - return 1; - case Qconvdir: - if(s == DEVDOTDOT){ - q.path = QID(0, Qprotodir); - q.type = QTDIR; - devdir(c, q, "ssl", 0, eve, 0555, dp); - return 1; - } - ds = dstate[CONV(c->qid)]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - switch(s) { - default: - return -1; - case 0: - q.path = QID(CONV(c->qid), Qctl); - p = "ctl"; - break; - case 1: - q.path = QID(CONV(c->qid), Qdata); - p = "data"; - break; - case 2: - q.path = QID(CONV(c->qid), Qsecretin); - p = "secretin"; - break; - case 3: - q.path = QID(CONV(c->qid), Qsecretout); - p = "secretout"; - break; - case 4: - q.path = QID(CONV(c->qid), Qencalgs); - p = "encalgs"; - break; - case 5: - q.path = QID(CONV(c->qid), Qhashalgs); - p = "hashalgs"; - break; - } - devdir(c, q, p, 0, nm, 0660, dp); - return 1; - case Qclonus: - devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp); - return 1; - default: - ds = dstate[CONV(c->qid)]; - if(ds != 0) - nm = ds->user; - else - nm = eve; - devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp); - return 1; - } -} - -static Chan* -sslattach(char *spec) -{ - Chan *c; - - c = devattach('D', spec); - c->qid.path = QID(0, Qtopdir); - c->qid.vers = 0; - c->qid.type = QTDIR; - return c; -} - -static Walkqid* -sslwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, nil, 0, sslgen); -} - -static int -sslstat(Chan *c, uchar *db, int n) -{ - return devstat(c, db, n, nil, 0, sslgen); -} - -static Chan* -sslopen(Chan *c, int omode) -{ - Dstate *s, **pp; - int ft; - - ft = TYPE(c->qid); - switch(ft) { - default: - panic("sslopen"); - case Qtopdir: - case Qprotodir: - case Qconvdir: - if(omode != OREAD) - error(Eperm); - break; - case Qclonus: - s = dsclone(c); - if(s == 0) - error(Enodev); - break; - case Qctl: - case Qdata: - case Qsecretin: - case Qsecretout: - if(waserror()) { - unlock(&dslock); - nexterror(); - } - lock(&dslock); - pp = &dstate[CONV(c->qid)]; - s = *pp; - if(s == 0) - dsnew(c, pp); - else { - devpermcheck(s->user, s->perm, omode); - s->ref++; - } - unlock(&dslock); - poperror(); - break; - case Qencalgs: - case Qhashalgs: - if(omode != OREAD) - error(Eperm); - break; - } - c->mode = openmode(omode); - c->flag |= COPEN; - c->offset = 0; - return c; -} - -static int -sslwstat(Chan *c, uchar *db, int n) -{ - Dir *dir; - Dstate *s; - int m; - - s = dstate[CONV(c->qid)]; - if(s == 0) - error(Ebadusefd); - if(strcmp(s->user, up->user) != 0) - error(Eperm); - - dir = smalloc(sizeof(Dir)+n); - m = convM2D(db, n, &dir[0], (char*)&dir[1]); - if(m == 0){ - free(dir); - error(Eshortstat); - } - - if(!emptystr(dir->uid)) - kstrdup(&s->user, dir->uid); - if(dir->mode != -1) - s->perm = dir->mode; - - free(dir); - return m; -} - -static void -sslclose(Chan *c) -{ - Dstate *s; - int ft; - - ft = TYPE(c->qid); - switch(ft) { - case Qctl: - case Qdata: - case Qsecretin: - case Qsecretout: - if((c->flag & COPEN) == 0) - break; - - s = dstate[CONV(c->qid)]; - if(s == 0) - break; - - lock(&dslock); - if(--s->ref > 0) { - unlock(&dslock); - break; - } - dstate[CONV(c->qid)] = 0; - unlock(&dslock); - - if(s->user != nil) - free(s->user); - sslhangup(s); - if(s->c) - cclose(s->c); - secfree(s->in.secret); - secfree(s->out.secret); - secfree(s->in.state); - secfree(s->out.state); - free(s); - - } -} - -/* - * make sure we have at least 'n' bytes in list 'l' - */ -static void -ensure(Dstate *s, Block **l, int n) -{ - int sofar, i; - Block *b, *bl; - - sofar = 0; - for(b = *l; b; b = b->next){ - sofar += BLEN(b); - if(sofar >= n) - return; - l = &b->next; - } - - while(sofar < n){ - bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0); - if(bl == 0) - nexterror(); - *l = bl; - i = 0; - for(b = bl; b; b = b->next){ - i += BLEN(b); - l = &b->next; - } - if(i == 0) - error(Ehungup); - sofar += i; - } -} - -/* - * copy 'n' bytes from 'l' into 'p' and free - * the bytes in 'l' - */ -static void -consume(Block **l, uchar *p, int n) -{ - Block *b; - int i; - - for(; *l && n > 0; n -= i){ - b = *l; - i = BLEN(b); - if(i > n) - i = n; - memmove(p, b->rp, i); - b->rp += i; - p += i; - if(BLEN(b) < 0) - panic("consume"); - if(BLEN(b)) - break; - *l = b->next; - freeb(b); - } -} - -/* - * give back n bytes -static void -regurgitate(Dstate *s, uchar *p, int n) -{ - Block *b; - - if(n <= 0) - return; - b = s->unprocessed; - if(s->unprocessed == nil || b->rp - b->base < n) { - b = allocb(n); - memmove(b->wp, p, n); - b->wp += n; - b->next = s->unprocessed; - s->unprocessed = b; - } else { - b->rp -= n; - memmove(b->rp, p, n); - } -} - */ - -/* - * remove at most n bytes from the queue, if discard is set - * dump the remainder - */ -static Block* -qtake(Block **l, int n, int discard) -{ - Block *nb, *b, *first; - int i; - - first = *l; - for(b = first; b; b = b->next){ - i = BLEN(b); - if(i == n){ - if(discard){ - freeblist(b->next); - *l = 0; - } else - *l = b->next; - b->next = 0; - return first; - } else if(i > n){ - i -= n; - if(discard){ - freeblist(b->next); - b->wp -= i; - *l = 0; - } else { - nb = allocb(i); - memmove(nb->wp, b->rp+n, i); - nb->wp += i; - b->wp -= i; - nb->next = b->next; - *l = nb; - } - b->next = 0; - if(BLEN(b) < 0) - panic("qtake"); - return first; - } else - n -= i; - if(BLEN(b) < 0) - panic("qtake"); - } - *l = 0; - return first; -} - -/* - * We can't let Eintr's lose data since the program - * doing the read may be able to handle it. The only - * places Eintr is possible is during the read's in consume. - * Therefore, we make sure we can always put back the bytes - * consumed before the last ensure. - */ -static Block* -sslbread(Chan *c, long n, ulong) -{ - Dstate * volatile s; - Block *b; - uchar consumed[3], *p; - int toconsume; - int len, pad; - - s = dstate[CONV(c->qid)]; - if(s == 0) - panic("sslbread"); - if(s->state == Sincomplete) - error(Ebadusefd); - - qlock(&s->in.q); - if(waserror()){ - qunlock(&s->in.q); - nexterror(); - } - - if(s->processed == 0){ - /* - * Read in the whole message. Until we've got it all, - * it stays on s->unprocessed, so that if we get Eintr, - * we'll pick up where we left off. - */ - ensure(s, &s->unprocessed, 3); - s->unprocessed = pullupblock(s->unprocessed, 2); - p = s->unprocessed->rp; - if(p[0] & 0x80){ - len = ((p[0] & 0x7f)<<8) | p[1]; - ensure(s, &s->unprocessed, len); - pad = 0; - toconsume = 2; - } else { - s->unprocessed = pullupblock(s->unprocessed, 3); - len = ((p[0] & 0x3f)<<8) | p[1]; - pad = p[2]; - if(pad > len){ - print("pad %d buf len %d\n", pad, len); - error("bad pad in ssl message"); - } - toconsume = 3; - } - ensure(s, &s->unprocessed, toconsume+len); - - /* skip header */ - consume(&s->unprocessed, consumed, toconsume); - - /* grab the next message and decode/decrypt it */ - b = qtake(&s->unprocessed, len, 0); - - if(blocklen(b) != len) - print("devssl: sslbread got wrong count %d != %d", blocklen(b), len); - - if(waserror()){ - qunlock(&s->in.ctlq); - if(b != nil) - freeb(b); - nexterror(); - } - qlock(&s->in.ctlq); - switch(s->state){ - case Sencrypting: - if(b == nil) - error("ssl message too short (encrypting)"); - b = decryptb(s, b); - break; - case Sdigesting: - b = pullupblock(b, s->diglen); - if(b == nil) - error("ssl message too short (digesting)"); - checkdigestb(s, b); - pullblock(&b, s->diglen); - len -= s->diglen; - break; - case Sdigenc: - b = decryptb(s, b); - b = pullupblock(b, s->diglen); - if(b == nil) - error("ssl message too short (dig+enc)"); - checkdigestb(s, b); - pullblock(&b, s->diglen); - len -= s->diglen; - break; - } - - /* remove pad */ - if(pad) - s->processed = qtake(&b, len - pad, 1); - else - s->processed = b; - b = nil; - s->in.mid++; - qunlock(&s->in.ctlq); - poperror(); - } - - /* return at most what was asked for */ - b = qtake(&s->processed, n, 0); - - qunlock(&s->in.q); - poperror(); - - return b; -} - -static long -sslread(Chan *c, void *a, long n, vlong off) -{ - Block * volatile b; - Block *nb; - uchar *va; - int i; - char buf[128]; - ulong offset = off; - int ft; - - if(c->qid.type & QTDIR) - return devdirread(c, a, n, 0, 0, sslgen); - - ft = TYPE(c->qid); - switch(ft) { - default: - error(Ebadusefd); - case Qctl: - ft = CONV(c->qid); - sprint(buf, "%d", ft); - return readstr(offset, a, n, buf); - case Qdata: - b = sslbread(c, n, offset); - break; - case Qencalgs: - return readstr(offset, a, n, encalgs); - break; - case Qhashalgs: - return readstr(offset, a, n, hashalgs); - break; - } - - if(waserror()){ - freeblist(b); - nexterror(); - } - - n = 0; - va = a; - for(nb = b; nb; nb = nb->next){ - i = BLEN(nb); - memmove(va+n, nb->rp, i); - n += i; - } - - freeblist(b); - poperror(); - - return n; -} - -static long -sslbwrite(Chan *c, Block *b, ulong) -{ - Dstate * volatile s; - long rv; - - s = dstate[CONV(c->qid)]; - if(s == nil) - panic("sslbwrite"); - - if(s->state == Sincomplete){ - freeb(b); - error(Ebadusefd); - } - - /* lock so split writes won't interleave */ - if(waserror()){ - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->out.q); - - rv = sslput(s, b); - - poperror(); - qunlock(&s->out.q); - - return rv; -} - -/* - * use SSL record format, add in count, digest and/or encrypt. - * the write is interruptable. if it is interrupted, we'll - * get out of sync with the far side. not much we can do about - * it since we don't know if any bytes have been written. - */ -static long -sslput(Dstate *s, Block * volatile b) -{ - Block *nb; - int h, n, m, pad, rv; - uchar *p; - int offset; - - if(waserror()){ - if(b != nil) - freeb(b); - nexterror(); - } - - rv = 0; - while(b != nil){ - m = n = BLEN(b); - h = s->diglen + 2; - - /* trim to maximum block size */ - pad = 0; - if(m > s->max){ - m = s->max; - } else if(s->blocklen != 1){ - pad = (m + s->diglen)%s->blocklen; - if(pad){ - if(m > s->maxpad){ - pad = 0; - m = s->maxpad; - } else { - pad = s->blocklen - pad; - h++; - } - } - } - - rv += m; - if(m != n){ - nb = allocb(m + h + pad); - memmove(nb->wp + h, b->rp, m); - nb->wp += m + h; - b->rp += m; - } else { - /* add header space */ - nb = padblock(b, h); - b = 0; - } - m += s->diglen; - - /* SSL style count */ - if(pad){ - nb = padblock(nb, -pad); - prng(nb->wp, pad); - nb->wp += pad; - m += pad; - - p = nb->rp; - p[0] = (m>>8); - p[1] = m; - p[2] = pad; - offset = 3; - } else { - p = nb->rp; - p[0] = (m>>8) | 0x80; - p[1] = m; - offset = 2; - } - - switch(s->state){ - case Sencrypting: - nb = encryptb(s, nb, offset); - break; - case Sdigesting: - nb = digestb(s, nb, offset); - break; - case Sdigenc: - nb = digestb(s, nb, offset); - nb = encryptb(s, nb, offset); - break; - } - - s->out.mid++; - - m = BLEN(nb); - devtab[s->c->type]->bwrite(s->c, nb, s->c->offset); - s->c->offset += m; - } - - poperror(); - return rv; -} - -static void -setsecret(OneWay *w, uchar *secret, int n) -{ - secfree(w->secret); - w->secret = secalloc(n); - memmove(w->secret, secret, n); - w->slen = n; -} - -static void -initDESkey(OneWay *w) -{ - secfree(w->state); - w->state = secalloc(sizeof(DESstate)); - if(w->slen >= 16) - setupDESstate(w->state, w->secret, w->secret+8); - else if(w->slen >= 8) - setupDESstate(w->state, w->secret, 0); - else - error("secret too short"); -} - -/* - * 40 bit DES is the same as 56 bit DES. However, - * 16 bits of the key are masked to zero. - */ -static void -initDESkey_40(OneWay *w) -{ - uchar key[8]; - - if(w->slen >= 8){ - memmove(key, w->secret, 8); - key[0] &= 0x0f; - key[2] &= 0x0f; - key[4] &= 0x0f; - key[6] &= 0x0f; - } - initDESkey(w); -} - -static void -initRC4key(OneWay *w) -{ - secfree(w->state); - w->state = secalloc(sizeof(RC4state)); - setupRC4state(w->state, w->secret, w->slen); -} - -/* - * 40 bit RC4 is the same as n-bit RC4. However, - * we ignore all but the first 40 bits of the key. - */ -static void -initRC4key_40(OneWay *w) -{ - if(w->slen > 5) - w->slen = 5; - initRC4key(w); -} - -/* - * 128 bit RC4 is the same as n-bit RC4. However, - * we ignore all but the first 128 bits of the key. - */ -static void -initRC4key_128(OneWay *w) -{ - if(w->slen > 16) - w->slen = 16; - initRC4key(w); -} - - -typedef struct Hashalg Hashalg; -struct Hashalg -{ - char *name; - int diglen; - DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*); -}; - -Hashalg hashtab[] = -{ - { "md4", MD4dlen, md4, }, - { "md5", MD5dlen, md5, }, - { "sha1", SHA1dlen, sha1, }, - { "sha", SHA1dlen, sha1, }, - { 0 } -}; - -static int -parsehashalg(char *p, Dstate *s) -{ - Hashalg *ha; - - for(ha = hashtab; ha->name; ha++){ - if(strcmp(p, ha->name) == 0){ - s->hf = ha->hf; - s->diglen = ha->diglen; - s->state &= ~Sclear; - s->state |= Sdigesting; - return 0; - } - } - return -1; -} - -typedef struct Encalg Encalg; -struct Encalg -{ - char *name; - int blocklen; - int alg; - void (*keyinit)(OneWay*); -}; - -#ifdef NOSPOOKS -static -Encalg encrypttab[] = -{ - { "descbc", 8, DESCBC, initDESkey, }, /* DEPRECATED -- use des_56_cbc */ - { "desecb", 8, DESECB, initDESkey, }, /* DEPRECATED -- use des_56_ecb */ - { "des_56_cbc", 8, DESCBC, initDESkey, }, - { "des_56_ecb", 8, DESECB, initDESkey, }, - { "des_40_cbc", 8, DESCBC, initDESkey_40, }, - { "des_40_ecb", 8, DESECB, initDESkey_40, }, - { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ - { "rc4_256", 1, RC4, initRC4key, }, - { "rc4_128", 1, RC4, initRC4key_128, }, - { "rc4_40", 1, RC4, initRC4key_40, }, - { 0 } -}; -#else -static -Encalg encrypttab[] = -{ - { "des_40_cbc", 8, DESCBC, initDESkey_40, }, - { "des_40_ecb", 8, DESECB, initDESkey_40, }, - { "rc4", 1, RC4, initRC4key_40, }, /* DEPRECATED -- use rc4_X */ - { "rc4_40", 1, RC4, initRC4key_40, }, - { 0 } -}; -#endif NOSPOOKS - -static int -parseencryptalg(char *p, Dstate *s) -{ - Encalg *ea; - - for(ea = encrypttab; ea->name; ea++){ - if(strcmp(p, ea->name) == 0){ - s->encryptalg = ea->alg; - s->blocklen = ea->blocklen; - (*ea->keyinit)(&s->in); - (*ea->keyinit)(&s->out); - s->state &= ~Sclear; - s->state |= Sencrypting; - return 0; - } - } - return -1; -} - -enum { - Cfd, - Calg, - Csin, - Csout, -}; - -static -Cmdtab sslcmds[] = { - {Cfd, "fd", 2 }, - {Calg, "alg", 0 }, - {Csin, "secretin", 2 }, - {Csout, "secretout", 2 }, -}; - -static long -sslwrite(Chan *c, void *a, long n, vlong) -{ - Dstate * volatile s; - Block * volatile b; - int m, t, i; - char *p, *e; - uchar *x; - Cmdbuf *cb; - Cmdtab *ct; - - s = dstate[CONV(c->qid)]; - if(s == 0) - panic("sslwrite"); - - t = TYPE(c->qid); - if(t == Qdata){ - if(s->state == Sincomplete) - error(Ebadusefd); - - /* lock should a write gets split over multiple records */ - if(waserror()){ - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->out.q); - - p = a; - e = p + n; - do { - m = e - p; - if(m > s->max) - m = s->max; - - b = allocb(m); - if(waserror()){ - freeb(b); - nexterror(); - } - memmove(b->wp, p, m); - poperror(); - b->wp += m; - - sslput(s, b); - - p += m; - } while(p < e); - - poperror(); - qunlock(&s->out.q); - return n; - } - - /* mutex with operations using what we're about to change */ - if(waserror()){ - qunlock(&s->in.ctlq); - qunlock(&s->out.q); - nexterror(); - } - qlock(&s->in.ctlq); - qlock(&s->out.q); - - switch(t){ - default: - panic("sslwrite"); - case Qsecretin: - setsecret(&s->in, a, n); - goto out; - case Qsecretout: - setsecret(&s->out, a, n); - goto out; - case Qctl: - break; - } - - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - ct = lookupcmd(cb, sslcmds, nelem(sslcmds)); - switch(ct->index){ - case Cfd: - s->c = buftochan(cb->f[1]); - - /* default is clear (msg delimiters only) */ - s->state = Sclear; - s->blocklen = 1; - s->diglen = 0; - s->maxpad = s->max = (1<<15) - s->diglen - 1; - s->in.mid = 0; - s->out.mid = 0; - break; - case Calg: - if(cb->nf < 2) - cmderror(cb, "no algorithms"); - - s->blocklen = 1; - s->diglen = 0; - - if(s->c == 0) - error("must set fd before algorithm"); - - s->state = Sclear; - s->maxpad = s->max = (1<<15) - s->diglen - 1; - if(strcmp(cb->f[1], "clear") == 0) - break; - - if(s->in.secret && s->out.secret == 0) - setsecret(&s->out, s->in.secret, s->in.slen); - if(s->out.secret && s->in.secret == 0) - setsecret(&s->in, s->out.secret, s->out.slen); - if(s->in.secret == 0 || s->out.secret == 0) - error("algorithm but no secret"); - - s->hf = 0; - s->encryptalg = Noencryption; - s->blocklen = 1; - - for(i=1; inf; i++){ - p = cb->f[i]; - if(parsehashalg(p, s) < 0) - if(parseencryptalg(p, s) < 0) - error("bad algorithm"); - } - - if(s->hf == 0 && s->encryptalg == Noencryption) - error("bad algorithm"); - - if(s->blocklen != 1){ - s->max = (1<<15) - s->diglen - 1; - s->max -= s->max % s->blocklen; - s->maxpad = (1<<14) - s->diglen - 1; - s->maxpad -= s->maxpad % s->blocklen; - } else - s->maxpad = s->max = (1<<15) - s->diglen - 1; - break; - case Csin: - p = cb->f[1]; - m = (strlen(p)*3)/2 + 1; - x = secalloc(m); - t = dec64(x, m, p, strlen(p)); - memset(p, 0, strlen(p)); - if(t <= 0){ - secfree(x); - error(Ebadarg); - } - setsecret(&s->in, x, t); - secfree(x); - break; - case Csout: - p = cb->f[1]; - m = (strlen(p)*3)/2 + 1; - x = secalloc(m); - t = dec64(x, m, p, strlen(p)); - memset(p, 0, strlen(p)); - if(t <= 0){ - secfree(x); - error(Ebadarg); - } - setsecret(&s->out, x, t); - secfree(x); - break; - } - poperror(); - free(cb); - -out: - qunlock(&s->in.ctlq); - qunlock(&s->out.q); - poperror(); - return n; -} - -static void -sslinit(void) -{ - struct Encalg *e; - struct Hashalg *h; - int n; - char *cp; - - n = 1; - for(e = encrypttab; e->name != nil; e++) - n += strlen(e->name) + 1; - cp = encalgs = smalloc(n); - for(e = encrypttab;;){ - strcpy(cp, e->name); - cp += strlen(e->name); - e++; - if(e->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; - - n = 1; - for(h = hashtab; h->name != nil; h++) - n += strlen(h->name) + 1; - cp = hashalgs = smalloc(n); - for(h = hashtab;;){ - strcpy(cp, h->name); - cp += strlen(h->name); - h++; - if(h->name == nil) - break; - *cp++ = ' '; - } - *cp = 0; -} - -Dev ssldevtab = { - 'D', - "ssl", - - devreset, - sslinit, - devshutdown, - sslattach, - sslwalk, - sslstat, - sslopen, - devcreate, - sslclose, - sslread, - sslbread, - sslwrite, - sslbwrite, - devremove, - sslwstat, -}; - -static Block* -encryptb(Dstate *s, Block *b, int offset) -{ - uchar *p, *ep, *p2, *ip, *eip; - DESstate *ds; - - switch(s->encryptalg){ - case DESECB: - ds = s->out.state; - ep = b->rp + BLEN(b); - for(p = b->rp + offset; p < ep; p += 8) - block_cipher(ds->expanded, p, 0); - break; - case DESCBC: - ds = s->out.state; - ep = b->rp + BLEN(b); - for(p = b->rp + offset; p < ep; p += 8){ - p2 = p; - ip = ds->ivec; - for(eip = ip+8; ip < eip; ) - *p2++ ^= *ip++; - block_cipher(ds->expanded, p, 0); - memmove(ds->ivec, p, 8); - } - break; - case RC4: - rc4(s->out.state, b->rp + offset, BLEN(b) - offset); - break; - } - return b; -} - -static Block* -decryptb(Dstate *s, Block *bin) -{ - Block *b, **l; - uchar *p, *ep, *tp, *ip, *eip; - DESstate *ds; - uchar tmp[8]; - int i; - - l = &bin; - for(b = bin; b; b = b->next){ - /* make sure we have a multiple of s->blocklen */ - if(s->blocklen > 1){ - i = BLEN(b); - if(i % s->blocklen){ - *l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen)); - if(b == 0) - error("ssl encrypted message too short"); - } - } - l = &b->next; - - /* decrypt */ - switch(s->encryptalg){ - case DESECB: - ds = s->in.state; - ep = b->rp + BLEN(b); - for(p = b->rp; p < ep; p += 8) - block_cipher(ds->expanded, p, 1); - break; - case DESCBC: - ds = s->in.state; - ep = b->rp + BLEN(b); - for(p = b->rp; p < ep;){ - memmove(tmp, p, 8); - block_cipher(ds->expanded, p, 1); - tp = tmp; - ip = ds->ivec; - for(eip = ip+8; ip < eip; ){ - *p++ ^= *ip; - *ip++ = *tp++; - } - } - break; - case RC4: - rc4(s->in.state, b->rp, BLEN(b)); - break; - } - } - return bin; -} - -static Block* -digestb(Dstate *s, Block *b, int offset) -{ - uchar *p; - DigestState ss; - uchar msgid[4]; - ulong n, h; - OneWay *w; - - w = &s->out; - - memset(&ss, 0, sizeof(ss)); - h = s->diglen + offset; - n = BLEN(b) - h; - - /* hash secret + message */ - (*s->hf)(w->secret, w->slen, 0, &ss); - (*s->hf)(b->rp + h, n, 0, &ss); - - /* hash message id */ - p = msgid; - n = w->mid; - *p++ = n>>24; - *p++ = n>>16; - *p++ = n>>8; - *p = n; - (*s->hf)(msgid, 4, b->rp + offset, &ss); - - return b; -} - -static void -checkdigestb(Dstate *s, Block *bin) -{ - uchar *p; - DigestState ss; - uchar msgid[4]; - int n, h; - OneWay *w; - uchar digest[128]; - Block *b; - - w = &s->in; - - memset(&ss, 0, sizeof(ss)); - - /* hash secret */ - (*s->hf)(w->secret, w->slen, 0, &ss); - - /* hash message */ - h = s->diglen; - for(b = bin; b; b = b->next){ - n = BLEN(b) - h; - if(n < 0) - panic("checkdigestb"); - (*s->hf)(b->rp + h, n, 0, &ss); - h = 0; - } - - /* hash message id */ - p = msgid; - n = w->mid; - *p++ = n>>24; - *p++ = n>>16; - *p++ = n>>8; - *p = n; - (*s->hf)(msgid, 4, digest, &ss); - - if(tsmemcmp(digest, bin->rp, s->diglen) != 0) - error("bad digest"); -} - -/* get channel associated with an fd */ -static Chan* -buftochan(char *p) -{ - Chan *c; - int fd; - - if(p == 0) - error(Ebadarg); - fd = strtoul(p, 0, 0); - if(fd < 0) - error(Ebadarg); - c = fdtochan(fd, ORDWR, 1, 1); /* error check and inc ref */ - if(devtab[c->type] == &ssldevtab){ - cclose(c); - error("cannot ssl encrypt devssl files"); - } - return c; -} - -/* hand up a digest connection */ -static void -sslhangup(Dstate *s) -{ - Block *b; - - qlock(&s->in.q); - for(b = s->processed; b; b = s->processed){ - s->processed = b->next; - freeb(b); - } - if(s->unprocessed){ - freeb(s->unprocessed); - s->unprocessed = 0; - } - s->state = Sincomplete; - qunlock(&s->in.q); -} - -static Dstate* -dsclone(Chan *ch) -{ - int i; - Dstate *ret; - - if(waserror()) { - unlock(&dslock); - nexterror(); - } - lock(&dslock); - ret = nil; - for(i=0; i= dshiwat) - dshiwat++; - memset(s, 0, sizeof(*s)); - s->state = Sincomplete; - s->ref = 1; - kstrdup(&s->user, up->user); - s->perm = 0660; - t = TYPE(ch->qid); - if(t == Qclonus) - t = Qctl; - ch->qid.path = QID(pp - dstate, t); - ch->qid.vers = 0; -} diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index 977693787..119147e8e 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -102,7 +102,6 @@ auth.$O devcons.$O: /sys/include/authsrv.h devcap.$O: /sys/include/libsec.h devfs.$O: /sys/include/libsec.h devsdp.$O: /sys/include/libsec.h -devssl.$O: /sys/include/libsec.h devtls.$O: /sys/include/libsec.h devswap.$O: /sys/include/libsec.h random.$O: /sys/include/libsec.h diff --git a/sys/src/cmd/cpu.c b/sys/src/cmd/cpu.c index f4083f315..e69de29bb 100644 --- a/sys/src/cmd/cpu.c +++ b/sys/src/cmd/cpu.c @@ -1,1237 +0,0 @@ -/* - * cpu.c - Make a connection to a cpu server - * - * Invoked by listen as 'cpu -R | -N service net netdir' - * by users as 'cpu [-h system] [-c cmd args ...]' - */ - -#include -#include -#include -#include -#include - -#define Maxfdata 8192 -#define MaxStr 128 - -void remoteside(void); -void fatal(char*, ...); -void lclnoteproc(int); -void rmtnoteproc(void); -void catcher(void*, char*); -void usage(void); -void writestr(int, char*, char*, int); -int readstr(int, char*, int); -char *rexcall(int*, char*, char*); -int setamalg(char*); -char *keyspec = ""; - -int notechan; -int exportpid; -char *system; -int cflag; -int nflag; -int dbg; -char *user; -char *patternfile; -char *origargs; - -char *srvname = "ncpu"; -char *exportfs = "/bin/oexportfs"; -char *ealgs = "rc4_256 sha1"; - -/* message size for exportfs; may be larger so we can do big graphics in CPU window */ -int msgsize = Maxfdata+IOHDRSZ; - -/* encryption mechanisms */ -static int clear(int); - -int (*encryption)(int) = clear; - -/* authentication mechanisms */ -static int netkeyauth(int); -static int netkeysrvauth(int, char*); -static int p9auth(int); -static int srvp9auth(int, char*); -static int noauth(int); -static int srvnoauth(int, char*); - -typedef struct AuthMethod AuthMethod; -struct AuthMethod { - char *name; /* name of method */ - int (*cf)(int); /* client side authentication */ - int (*sf)(int, char*); /* server side authentication */ -} authmethod[] = { - { "p9", p9auth, srvp9auth,}, - { "netkey", netkeyauth, netkeysrvauth,}, - { "none", noauth, srvnoauth,}, - { nil, nil} -}; -AuthMethod *am = authmethod; /* default is p9 */ - -int setam(char*); - -char *aan = "/bin/aan"; -char *anstring = "tcp!*!0"; -char *filterp = nil; - -int filter(int fd, char *host); - -void -usage(void) -{ - fprint(2, "usage: cpu [-p] [-h system] [-u user] [-a authmethod] " - "[-e 'crypt hash'] [-k keypattern] [-P patternfile] " - "[-c cmd arg ...]\n"); - exits("usage"); -} - -/* - * reading /proc/pid/args yields either "name args" or "name [display args]", - * so return only args or display args. - */ -static char * -procgetname(void) -{ - int fd, n; - char *lp, *rp; - char buf[256]; - - snprint(buf, sizeof buf, "#p/%d/args", getpid()); - if((fd = open(buf, OREAD)) < 0) - return strdup(""); - *buf = '\0'; - n = read(fd, buf, sizeof buf-1); - close(fd); - if (n >= 0) - buf[n] = '\0'; - if ((lp = strchr(buf, '[')) == nil || (rp = strrchr(buf, ']')) == nil) { - lp = strchr(buf, ' '); - if (lp == nil) - return strdup(""); - else - return strdup(lp+1); - } - *rp = '\0'; - return strdup(lp+1); -} - -void -main(int argc, char **argv) -{ - char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *s, *err; - int ac, fd, ms, data; - char *av[10]; - - quotefmtinstall(); - origargs = procgetname(); - /* see if we should use a larger message size */ - fd = open("/dev/draw", OREAD); - if(fd >= 0){ - ms = iounit(fd); - if(msgsize < ms+IOHDRSZ) - msgsize = ms+IOHDRSZ; - close(fd); - } - - user = getuser(); - if(user == nil) - fatal("can't read user name: %r"); - ARGBEGIN{ - case 'a': - p = EARGF(usage()); - if(setam(p) < 0) - fatal("unknown auth method %s", p); - break; - case 'e': - ealgs = EARGF(usage()); - if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) - ealgs = nil; - break; - case 'd': - dbg++; - break; - case 'f': - /* ignored but accepted for compatibility */ - break; - case 'n': - /* must be specified before -R/-O */ - nflag++; - break; - case 'A': - anstring = EARGF(usage()); - break; - case 'R': /* From listen */ - remoteside(); - break; - case 'h': - system = EARGF(usage()); - break; - case 'c': - cflag++; - s = cmd; - *s++ = '!'; - *s = 0; - while(p = ARGF()) - s = seprint(s, cmd+sizeof(cmd), " %q", p); - break; - case 'k': - keyspec = smprint("%s %s", keyspec, EARGF(usage())); - break; - case 'P': - patternfile = EARGF(usage()); - break; - case 'u': - user = EARGF(usage()); - keyspec = smprint("%s user=%s", keyspec, user); - break; - case 'p': - filterp = aan; - break; - default: - usage(); - }ARGEND; - - - if(argc != 0) - usage(); - - if(system == nil) { - p = getenv("cpu"); - if(p == 0) - fatal("set $cpu"); - system = p; - } - - if(err = rexcall(&data, system, srvname)) - fatal("%s: %s: %r", err, system); - - procsetname("%s", origargs); - /* Tell the remote side the command to execute and where our working directory is */ - if(cflag) - writestr(data, cmd, "command", 0); - if(getwd(dat, sizeof(dat)) == 0) - writestr(data, "NO", "dir", 0); - else - writestr(data, dat, "dir", 0); - - /* start up a process to pass along notes */ - lclnoteproc(data); - - /* - * Wait for the other end to execute and start our file service - * of /mnt/term - */ - if(readstr(data, buf, sizeof(buf)) < 0) - fatal("waiting for FS: %r"); - if(strncmp("FS", buf, 2) != 0) { - print("remote cpu: %s", buf); - exits(buf); - } - - /* Begin serving the gnot namespace */ - close(0); - dup(data, 0); - close(data); - - sprint(buf, "%d", msgsize); - ac = 0; - av[ac++] = exportfs; - av[ac++] = "-m"; - av[ac++] = buf; - if(dbg) - av[ac++] = "-d"; - if(patternfile != nil){ - av[ac++] = "-P"; - av[ac++] = patternfile; - } - av[ac] = nil; - exec(exportfs, av); - fatal("starting exportfs: %r"); -} - -void -fatal(char *fmt, ...) -{ - char buf[1024]; - va_list arg; - - va_start(arg, fmt); - vsnprint(buf, sizeof(buf), fmt, arg); - va_end(arg); - fprint(2, "cpu: %s\n", buf); - syslog(0, "cpu", "%s", buf); - exits(buf); -} - -char *negstr = "negotiating authentication method"; - -/* Invoked with stdin and stdout connected to the network connection */ -void -remoteside(void) -{ - char user[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr]; - int i, n, fd, badchdir, gotcmd; - - rfork(RFENVG); - putenv("service", "cpu"); - fd = 0; - - /* negotiate authentication mechanism */ - n = readstr(fd, cmd, sizeof(cmd)); - if(n < 0) - fatal("authenticating: %r"); - filterp = nil; - if(strcmp(cmd, "aan") == 0){ - filterp = aan; - writestr(fd, "", nil, 1); - n = readstr(fd, cmd, sizeof(cmd)); - if(n < 0) - fatal("authenticating: %r"); - } - if(setamalg(cmd) < 0 || (nflag == 0 && am->sf == srvnoauth)) { - writestr(fd, "unsupported auth method", nil, 0); - fatal("bad auth method %s", cmd); - } else - writestr(fd, "", "", 1); - - if((fd = (*am->sf)(fd, user)) < 0) - fatal("srvauth: %r"); - if((fd = filter(fd, nil)) < 0) - fatal("filter: %r"); - if((fd = encryption(fd)) < 0) - fatal("encrypt: %r"); - - /* Now collect invoking cpu's current directory or possibly a command */ - gotcmd = 0; - if(readstr(fd, xdir, sizeof(xdir)) < 0) - fatal("dir/cmd: %r"); - if(xdir[0] == '!') { - strcpy(cmd, &xdir[1]); - gotcmd = 1; - if(readstr(fd, xdir, sizeof(xdir)) < 0) - fatal("dir: %r"); - } - - /* Establish the new process at the current working directory of the gnot */ - badchdir = 0; - if(strcmp(xdir, "NO") != 0) - if(chdir(xdir) < 0) - badchdir = 1; - - /* Start the gnot serving its namespace */ - writestr(fd, "FS", "FS", 0); - writestr(fd, "/", "exportfs dir", 0); - - n = read(fd, buf, sizeof(buf)); - if(n != 2 || buf[0] != 'O' || buf[1] != 'K') - exits("remote tree"); - - /* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */ - strcpy(buf, VERSION9P); - if(fversion(fd, 64*1024, buf, sizeof buf) < 0) - exits("fversion failed"); - if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") == -1) - exits("mount failed"); - - close(fd); - - /* the remote noteproc uses the mount so it must follow it */ - rmtnoteproc(); - - for(i = 0; i < 3; i++) - close(i); - - if(open("/mnt/term/dev/cons", OREAD) != 0) - exits("open stdin"); - if(open("/mnt/term/dev/cons", OWRITE) != 1) - exits("open stdout"); - dup(1, 2); - - if(badchdir) - print("cpu: failed to chdir to '%s'\n", xdir); - - if(gotcmd) - execl("/bin/rc", "rc", "-lc", cmd, nil); - else - execl("/bin/rc", "rc", "-li", nil); - fatal("exec shell: %r"); -} - -char* -rexcall(int *fd, char *host, char *service) -{ - char *na; - char err[ERRMAX]; - char msg[MaxStr]; - int n; - - na = netmkaddr(host, 0, service); - procsetname("dialing %s", na); - if((*fd = dial(na, 0, 0, 0)) < 0) - return "can't dial"; - - /* negotiate aan filter extension */ - if(filterp == aan){ - writestr(*fd, "aan", "negotiating aan", 0); - n = readstr(*fd, err, sizeof err); - if(n < 0) - return "negotiating aan"; - if(*err){ - errstr(err, sizeof err); - return negstr; - } - } - - /* negotiate authentication mechanism */ - if(ealgs != nil) - snprint(msg, sizeof(msg), "%s %s", am->name, ealgs); - else - snprint(msg, sizeof(msg), "%s", am->name); - procsetname("writing %s", msg); - writestr(*fd, msg, negstr, 0); - procsetname("awaiting auth method"); - n = readstr(*fd, err, sizeof err); - if(n < 0) - return negstr; - if(*err){ - errstr(err, sizeof err); - return negstr; - } - - /* authenticate */ - procsetname("%s: auth via %s", origargs, am->name); - if((*fd = (*am->cf)(*fd)) < 0) - return "can't authenticate"; - if((*fd = filter(*fd, system)) < 0) - return "can't filter"; - if((*fd = encryption(*fd)) < 0) - return "can't encrypt"; - return nil; -} - -void -writestr(int fd, char *str, char *thing, int ignore) -{ - int l, n; - - l = strlen(str); - n = write(fd, str, l+1); - if(!ignore && n < 0) - fatal("writing network: %s: %r", thing); -} - -int -readstr(int fd, char *str, int len) -{ - int n; - - while(len) { - n = read(fd, str, 1); - if(n < 0) - return -1; - if(n == 0){ - werrstr("hung up"); - return -1; - } - if(*str == '\0') - return 0; - str++; - len--; - } - return -1; -} - -static int -readln(char *buf, int n) -{ - int i; - char *p; - - n--; /* room for \0 */ - p = buf; - for(i=0; ichal, "challenge", 1); - if(readstr(fd, response, sizeof response) < 0) - return -1; - ch->resp = response; - ch->nresp = strlen(response); - if((ai = auth_response(ch)) != nil) - break; - } - auth_freechal(ch); - if(ai == nil) - return -1; - writestr(fd, "", "challenge", 1); - if(auth_chuid(ai, 0) < 0) - fatal("newns: %r"); - setnetuser(fd, ai->cuid); - auth_freeAI(ai); - return fd; -} - -static int -clear(int fd) -{ - return fd; -} - -static char sslsecret[2][21]; - -static int -sslencrypt(int fd) -{ - return pushssl(fd, ealgs, sslsecret[0], sslsecret[1], nil); -} - -static void -mksecret(char *t, uchar *f) -{ - sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", - f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); -} - -static int -sslsetup(int fd, uchar *secret, int nsecret, int isclient) -{ - uchar key[16], digest[SHA1dlen]; - int i; - - if(ealgs == nil) - return fd; - - if(nsecret < 8){ - werrstr("secret too small to ssl"); - return -1; - } - memmove(key+4, secret, 8); - - /* exchange random numbers */ - srand(truerand()); - - if(isclient){ - for(i = 0; i < 4; i++) - key[i] = rand(); - if(write(fd, key, 4) != 4) - return -1; - if(readn(fd, key+12, 4) != 4) - return -1; - } else { - for(i = 0; i < 4; i++) - key[i+12] = rand(); - if(readn(fd, key, 4) != 4) - return -1; - if(write(fd, key+12, 4) != 4) - return -1; - } - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(sslsecret[isclient == 0], digest); - mksecret(sslsecret[isclient != 0], digest+10); - - encryption = sslencrypt; - - return fd; -} - -/* - * plan9 authentication followed by rc4 encryption - */ -static int -p9auth(int fd) -{ - AuthInfo *ai; - - ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec); - if(ai == nil) - return -1; - fd = sslsetup(fd, ai->secret, ai->nsecret, 1); - auth_freeAI(ai); - return fd; -} - -static int -noauth(int fd) -{ - ealgs = nil; - return fd; -} - -static int -srvnoauth(int fd, char *user) -{ - strecpy(user, user+MaxStr, getuser()); - ealgs = nil; - newns(user, nil); - return fd; -} - -static int -srvp9auth(int fd, char *user) -{ - AuthInfo *ai; - - ai = auth_proxy(fd, nil, "proto=p9any role=server %s", keyspec); - if(ai == nil) - return -1; - if(auth_chuid(ai, nil) < 0) - fatal("newns: %r"); - setnetuser(fd, ai->cuid); - snprint(user, MaxStr, "%s", ai->cuid); - fd = sslsetup(fd, ai->secret, ai->nsecret, 0); - auth_freeAI(ai); - return fd; -} - -/* - * set authentication mechanism - */ -int -setam(char *name) -{ - for(am = authmethod; am->name != nil; am++) - if(strcmp(am->name, name) == 0) - return 0; - am = authmethod; - return -1; -} - -/* - * set authentication mechanism and encryption/hash algs - */ -int -setamalg(char *s) -{ - ealgs = strchr(s, ' '); - if(ealgs != nil) - *ealgs++ = 0; - return setam(s); -} - -int -filter(int fd, char *host) -{ - char addr[128], buf[256], *s, *file, *argv[16]; - int p[2], lfd, flags, len, argc; - - if(filterp == nil) - return fd; - procsetname("filter %s", filterp); - flags = RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND; - if(host == nil){ - /* remote side */ - if(announce(anstring, addr) < 0) - fatal("filter: Cannot announce %s: %r", anstring); - snprint(buf, sizeof(buf), "%s/local", addr); - if((lfd = open(buf, OREAD)) < 0) - fatal("filter: Cannot open %s: %r", buf); - if((len = read(lfd, buf, sizeof buf - 1)) < 0) - fatal("filter: Cannot read %s: %r", buf); - close(lfd); - buf[len] = 0; - if(s = strchr(buf, '\n')) - len = s - buf; - if(write(fd, buf, len) != len) - fatal("filter: cannot write port; %r"); - } else { - /* client side */ - flags |= RFNOTEG; - if((len = read(fd, buf, sizeof buf - 1)) < 0) - fatal("filter: cannot read port; %r"); - buf[len] = '\0'; - if((s = strrchr(buf, '!')) == nil) - fatal("filter: malformed remote port: %s", buf); - strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1)); - strecpy(strrchr(addr, '!'), addr+sizeof(addr), s); - } - - snprint(buf, sizeof(buf), "%s", filterp); - if((argc = tokenize(buf, argv, nelem(argv)-3)) <= 0) - fatal("filter: empty command"); - if(host) - argv[argc++] = "-c"; - argv[argc++] = addr; - argv[argc] = nil; - file = argv[0]; - if(s = strrchr(argv[0], '/')) - argv[0] = s+1; - - if(pipe(p) < 0) - fatal("filter: pipe; %r"); - - switch(rfork(flags)) { - case -1: - fatal("filter: rfork; %r\n"); - case 0: - if (dup(p[0], 1) < 0) - fatal("filter: Cannot dup to 1; %r"); - if (dup(p[0], 0) < 0) - fatal("filter: Cannot dup to 0; %r"); - close(p[0]); - close(p[1]); - exec(file, argv); - fatal("filter: exec; %r"); - default: - close(fd); - close(p[0]); - } - return p[1]; -} - -char *rmtnotefile = "/mnt/term/dev/cpunote"; - -/* - * loop reading /mnt/term/dev/note looking for notes. - * The child returns to start the shell. - */ -void -rmtnoteproc(void) -{ - int n, fd, pid, notepid; - char buf[256]; - - /* new proc returns to start shell */ - pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM); - switch(pid){ - case -1: - syslog(0, "cpu", "cpu -R: can't start noteproc: %r"); - return; - case 0: - return; - } - - /* new proc reads notes from other side and posts them to shell */ - switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){ - case -1: - syslog(0, "cpu", "cpu -R: can't start wait proc: %r"); - _exits(0); - case 0: - fd = open(rmtnotefile, OREAD); - if(fd < 0) - _exits(0); - - for(;;){ - n = read(fd, buf, sizeof(buf)-1); - if(n <= 0){ - postnote(PNGROUP, pid, "hangup"); - _exits(0); - } - buf[n] = 0; - postnote(PNGROUP, pid, buf); - } - } - - /* original proc waits for shell proc to die and kills note proc */ - for(;;){ - n = waitpid(); - if(n < 0 || n == pid) - break; - } - postnote(PNPROC, notepid, "kill"); - _exits(0); -} - -enum -{ - Qdir, - Qcpunote, - - Nfid = 32, -}; - -struct { - char *name; - Qid qid; - ulong perm; -} fstab[] = -{ - [Qdir] { ".", {Qdir, 0, QTDIR}, DMDIR|0555 }, - [Qcpunote] { "cpunote", {Qcpunote, 0}, 0444 }, -}; - -typedef struct Note Note; -struct Note -{ - Note *next; - char msg[ERRMAX]; -}; - -typedef struct Request Request; -struct Request -{ - Request *next; - Fcall f; -}; - -typedef struct Fid Fid; -struct Fid -{ - int fid; - int file; - int omode; -}; -Fid fids[Nfid]; - -struct { - Lock; - Note *nfirst, *nlast; - Request *rfirst, *rlast; -} nfs; - -int -fsreply(int fd, Fcall *f) -{ - uchar buf[IOHDRSZ+Maxfdata]; - int n; - - if(dbg) - fprint(2, "notefs: <-%F\n", f); - n = convS2M(f, buf, sizeof buf); - if(n > 0){ - if(write(fd, buf, n) != n){ - close(fd); - return -1; - } - } - return 0; -} - -/* match a note read request with a note, reply to the request */ -int -kick(int fd) -{ - Request *rp; - Note *np; - int rv; - - for(;;){ - lock(&nfs); - rp = nfs.rfirst; - np = nfs.nfirst; - if(rp == nil || np == nil){ - unlock(&nfs); - break; - } - nfs.rfirst = rp->next; - nfs.nfirst = np->next; - unlock(&nfs); - - rp->f.type = Rread; - rp->f.count = strlen(np->msg); - rp->f.data = np->msg; - rv = fsreply(fd, &rp->f); - free(rp); - free(np); - if(rv < 0) - return -1; - } - return 0; -} - -void -flushreq(int tag) -{ - Request **l, *rp; - - lock(&nfs); - for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){ - rp = *l; - if(rp->f.tag == tag){ - *l = rp->next; - unlock(&nfs); - free(rp); - return; - } - } - unlock(&nfs); -} - -Fid* -getfid(int fid) -{ - int i, freefid; - - freefid = -1; - for(i = 0; i < Nfid; i++){ - if(freefid < 0 && fids[i].file < 0) - freefid = i; - if(fids[i].fid == fid) - return &fids[i]; - } - if(freefid >= 0){ - fids[freefid].fid = fid; - return &fids[freefid]; - } - return nil; -} - -int -fsstat(int fd, Fid *fid, Fcall *f) -{ - Dir d; - uchar statbuf[256]; - - memset(&d, 0, sizeof(d)); - d.name = fstab[fid->file].name; - d.uid = user; - d.gid = user; - d.muid = user; - d.qid = fstab[fid->file].qid; - d.mode = fstab[fid->file].perm; - d.atime = d.mtime = time(0); - f->stat = statbuf; - f->nstat = convD2M(&d, statbuf, sizeof statbuf); - return fsreply(fd, f); -} - -int -fsread(int fd, Fid *fid, Fcall *f) -{ - Dir d; - uchar buf[256]; - Request *rp; - - switch(fid->file){ - default: - return -1; - case Qdir: - if(f->offset == 0 && f->count >0){ - memset(&d, 0, sizeof(d)); - d.name = fstab[Qcpunote].name; - d.uid = user; - d.gid = user; - d.muid = user; - d.qid = fstab[Qcpunote].qid; - d.mode = fstab[Qcpunote].perm; - d.atime = d.mtime = time(0); - f->count = convD2M(&d, buf, sizeof buf); - f->data = (char*)buf; - } else - f->count = 0; - return fsreply(fd, f); - case Qcpunote: - rp = mallocz(sizeof(*rp), 1); - if(rp == nil) - return -1; - rp->f = *f; - lock(&nfs); - if(nfs.rfirst == nil) - nfs.rfirst = rp; - else - nfs.rlast->next = rp; - nfs.rlast = rp; - unlock(&nfs); - return kick(fd);; - } -} - -char Eperm[] = "permission denied"; -char Enofile[] = "out of files"; -char Enotdir[] = "not a directory"; - -void -notefs(int fd) -{ - uchar buf[IOHDRSZ+Maxfdata]; - int i, n, ncpunote; - Fcall f; - Qid wqid[MAXWELEM]; - Fid *fid, *nfid; - int doreply; - - rfork(RFNOTEG); - fmtinstall('F', fcallfmt); - - for(n = 0; n < Nfid; n++){ - fids[n].file = -1; - fids[n].omode = -1; - } - - ncpunote = 0; - for(;;){ - n = read9pmsg(fd, buf, sizeof(buf)); - if(n <= 0 || convM2S(buf, n, &f) != n) - break; - if(dbg) - fprint(2, "notefs: ->%F\n", &f); - doreply = 1; - fid = getfid(f.fid); - if(fid == nil){ -nofids: - f.type = Rerror; - f.ename = Enofile; - fsreply(fd, &f); - continue; - } - switch(f.type++){ - default: - f.type = Rerror; - f.ename = "unknown type"; - break; - case Tflush: - flushreq(f.oldtag); - break; - case Tversion: - if(f.msize > IOHDRSZ+Maxfdata) - f.msize = IOHDRSZ+Maxfdata; - break; - case Tauth: - f.type = Rerror; - f.ename = "authentication not required"; - break; - case Tattach: - f.qid = fstab[Qdir].qid; - fid->file = Qdir; - break; - case Twalk: - nfid = nil; - if(f.newfid != f.fid){ - nfid = getfid(f.newfid); - if(nfid == nil) - goto nofids; - nfid->file = fid->file; - fid = nfid; - } - for(i=0; ifile != Qdir){ - f.type = Rerror; - f.ename = Enotdir; - break; - } - if(strcmp(f.wname[i], "..") == 0){ - wqid[i] = fstab[Qdir].qid; - continue; - } - if(strcmp(f.wname[i], "cpunote") != 0){ - if(i == 0){ - f.type = Rerror; - f.ename = "file does not exist"; - } - break; - } - fid->file = Qcpunote; - wqid[i] = fstab[Qcpunote].qid; - } - if(nfid != nil && (f.type == Rerror || i < f.nwname)) - nfid ->file = -1; - if(f.type != Rerror){ - f.nwqid = i; - for(i=0; iomode = f.mode; - if(fid->file == Qcpunote) - ncpunote++; - f.qid = fstab[fid->file].qid; - f.iounit = 0; - break; - case Tread: - if(fsread(fd, fid, &f) < 0) - goto err; - doreply = 0; - break; - case Tclunk: - if(fid->omode != -1 && fid->file == Qcpunote){ - ncpunote--; - if(ncpunote == 0) /* remote side is done */ - goto err; - } - fid->file = -1; - fid->omode = -1; - break; - case Tstat: - if(fsstat(fd, fid, &f) < 0) - goto err; - doreply = 0; - break; - case Tcreate: - case Twrite: - case Tremove: - case Twstat: - f.type = Rerror; - f.ename = Eperm; - break; - } - if(doreply) - if(fsreply(fd, &f) < 0) - break; - } -err: - if(dbg) - fprint(2, "notefs exiting: %r\n"); - werrstr("success"); - postnote(PNGROUP, exportpid, "kill"); - if(dbg) - fprint(2, "postnote PNGROUP %d: %r\n", exportpid); - close(fd); -} - -char notebuf[ERRMAX]; - -void -catcher(void*, char *text) -{ - int n; - - n = strlen(text); - if(n >= sizeof(notebuf)) - n = sizeof(notebuf)-1; - memmove(notebuf, text, n); - notebuf[n] = '\0'; - noted(NCONT); -} - -/* - * mount in /dev a note file for the remote side to read. - */ -void -lclnoteproc(int netfd) -{ - Waitmsg *w; - Note *np; - int pfd[2]; - int pid; - - if(pipe(pfd) < 0){ - fprint(2, "cpu: can't start note proc: pipe: %r\n"); - return; - } - - /* new proc mounts and returns to start exportfs */ - switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){ - default: - exportpid = pid; - break; - case -1: - fprint(2, "cpu: can't start note proc: rfork: %r\n"); - return; - case 0: - close(pfd[0]); - if(mount(pfd[1], -1, "/dev", MBEFORE, "") == -1) - fprint(2, "cpu: can't mount note proc: %r\n"); - close(pfd[1]); - return; - } - - close(netfd); - close(pfd[1]); - - /* new proc listens for note file system rpc's */ - switch(rfork(RFPROC|RFNAMEG|RFMEM)){ - case -1: - fprint(2, "cpu: can't start note proc: rfork1: %r\n"); - _exits(0); - case 0: - notefs(pfd[0]); - _exits(0); - } - - /* original proc waits for notes */ - notify(catcher); - w = nil; - for(;;) { - *notebuf = 0; - free(w); - w = wait(); - if(w == nil) { - if(*notebuf == 0) - break; - np = mallocz(sizeof(Note), 1); - if(np != nil){ - strcpy(np->msg, notebuf); - lock(&nfs); - if(nfs.nfirst == nil) - nfs.nfirst = np; - else - nfs.nlast->next = np; - nfs.nlast = np; - unlock(&nfs); - kick(pfd[0]); - } - unlock(&nfs); - } else if(w->pid == exportpid) - break; - } - - if(w == nil) - exits(nil); - exits(0); -/* exits(w->msg); */ -} diff --git a/sys/src/libc/9sys/mkfile b/sys/src/libc/9sys/mkfile index fe581f14b..0371c865f 100644 --- a/sys/src/libc/9sys/mkfile +++ b/sys/src/libc/9sys/mkfile @@ -33,7 +33,6 @@ OFILES=\ postnote.$O\ privalloc.$O\ procsetname.$O\ - pushssl.$O\ pushtls.$O\ putenv.$O\ qlock.$O\