From 7efbea82c63846a281db36d3854e13d3ab5498d2 Mon Sep 17 00:00:00 2001 From: Ori Bernstein Date: Mon, 13 Dec 2021 02:17:02 +0000 Subject: [PATCH] devssl, cpu, import, oexportfs: delete SSL is implemented by devssl. It's extremely obsolete by now, and is not used anywhere but cpu, import, and oexportfs. This change strips out the devssl bits, but does not (yet) remove the code from libsec. --- sys/include/libc.h | 1 - sys/man/1/cpu | 237 ------ sys/man/4/import | 221 ------ sys/man/4/oexportfs | 143 ---- sys/src/9/bcm/pi | 1 - sys/src/9/bcm/pi2 | 1 - sys/src/9/bcm/picpuf | 1 - sys/src/9/bcm64/pi3 | 1 - sys/src/9/bcm64/pi4 | 1 - sys/src/9/cycv/cycv | 1 - sys/src/9/kw/plug | 1 - sys/src/9/mtx/mtx | 1 - sys/src/9/omap/beagle | 1 - sys/src/9/pc/pc | 1 - sys/src/9/pc64/pc64 | 1 - sys/src/9/port/devssl.c | 1462 ------------------------------------- sys/src/9/port/portmkfile | 1 - sys/src/cmd/cpu.c | 1237 ------------------------------- sys/src/libc/9sys/mkfile | 1 - 19 files changed, 3314 deletions(-) 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\