586 lines
12 KiB
C
586 lines
12 KiB
C
|
|
/* network login client */
|
||
|
|
#include <u.h>
|
||
|
|
#include <libc.h>
|
||
|
|
#include <mp.h>
|
||
|
|
#include <libsec.h>
|
||
|
|
#include <authsrv.h>
|
||
|
|
#include "SConn.h"
|
||
|
|
#include "secstore.h"
|
||
|
|
enum{ CHK = 16, MAXFILES = 100 };
|
||
|
|
|
||
|
|
typedef struct AuthConn{
|
||
|
|
SConn *conn;
|
||
|
|
char pass[64];
|
||
|
|
int passlen;
|
||
|
|
} AuthConn;
|
||
|
|
|
||
|
|
int verbose;
|
||
|
|
Nvrsafe nvr;
|
||
|
|
char *SECSTORE_DIR;
|
||
|
|
|
||
|
|
void
|
||
|
|
usage(void)
|
||
|
|
{
|
||
|
|
fprint(2, "usage: secstore [-cin] [-g getfile] [-p putfile] [-r rmfile] [-s tcp!server!5356] [-u user] [-v]\n");
|
||
|
|
exits("usage");
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
getfile(SConn *conn, char *gf, uchar **buf, ulong *buflen, uchar *key, int nkey)
|
||
|
|
{
|
||
|
|
int fd = -1;
|
||
|
|
int i, n, nr, nw, len;
|
||
|
|
char s[Maxmsg+1];
|
||
|
|
uchar skey[SHA1dlen], ib[Maxmsg+CHK], *ibr, *ibw, *bufw, *bufe;
|
||
|
|
AESstate aes;
|
||
|
|
DigestState *sha;
|
||
|
|
|
||
|
|
if(strchr(gf, '/')){
|
||
|
|
fprint(2, "simple filenames, not paths like %s\n", gf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
memset(&aes, 0, sizeof aes);
|
||
|
|
|
||
|
|
snprint(s, Maxmsg, "GET %s\n", gf);
|
||
|
|
conn->write(conn, (uchar*)s, strlen(s));
|
||
|
|
|
||
|
|
/* get file size */
|
||
|
|
s[0] = '\0';
|
||
|
|
bufw = bufe = nil;
|
||
|
|
if(readstr(conn, s) < 0){
|
||
|
|
fprint(2, "remote: %s\n", s);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
len = atoi(s);
|
||
|
|
if(len == -1){
|
||
|
|
fprint(2, "remote file %s does not exist\n", gf);
|
||
|
|
return -1;
|
||
|
|
}else if(len == -3){
|
||
|
|
fprint(2, "implausible filesize for %s\n", gf);
|
||
|
|
return -1;
|
||
|
|
}else if(len < 0){
|
||
|
|
fprint(2, "GET refused for %s\n", gf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if(buf != nil){
|
||
|
|
*buflen = len - AESbsize - CHK;
|
||
|
|
*buf = bufw = emalloc(len);
|
||
|
|
bufe = bufw + len;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* directory listing */
|
||
|
|
if(strcmp(gf,".")==0){
|
||
|
|
if(buf != nil)
|
||
|
|
*buflen = len;
|
||
|
|
for(i=0; i < len; i += n){
|
||
|
|
if((n = conn->read(conn, (uchar*)s, Maxmsg)) <= 0){
|
||
|
|
fprint(2, "empty file chunk\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if(buf == nil)
|
||
|
|
write(1, s, n);
|
||
|
|
else
|
||
|
|
memmove((*buf)+i, s, n);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* conn is already encrypted against wiretappers,
|
||
|
|
but gf is also encrypted against server breakin. */
|
||
|
|
if(buf == nil && (fd =create(gf, OWRITE, 0600)) < 0){
|
||
|
|
fprint(2, "can't open %s: %r\n", gf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
ibr = ibw = ib;
|
||
|
|
for(nr=0; nr < len;){
|
||
|
|
if((n = conn->read(conn, ibw, Maxmsg)) <= 0){
|
||
|
|
fprint(2, "empty file chunk n=%d nr=%d len=%d: %r\n", n, nr, len);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
nr += n;
|
||
|
|
ibw += n;
|
||
|
|
if(!aes.setup){ /* first time, read 16 byte IV */
|
||
|
|
if(n < AESbsize){
|
||
|
|
fprint(2, "no IV in file\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
sha = sha1((uchar*)"aescbc file", 11, nil, nil);
|
||
|
|
sha1(key, nkey, skey, sha);
|
||
|
|
setupAESstate(&aes, skey, AESbsize, ibr);
|
||
|
|
memset(skey, 0, sizeof skey);
|
||
|
|
ibr += AESbsize;
|
||
|
|
n -= AESbsize;
|
||
|
|
}
|
||
|
|
aesCBCdecrypt(ibw-n, n, &aes);
|
||
|
|
n = ibw-ibr-CHK;
|
||
|
|
if(n > 0){
|
||
|
|
if(buf == nil){
|
||
|
|
nw = write(fd, ibr, n);
|
||
|
|
if(nw != n){
|
||
|
|
fprint(2, "write error on %s", gf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
assert(bufw+n <= bufe);
|
||
|
|
memmove(bufw, ibr, n);
|
||
|
|
bufw += n;
|
||
|
|
}
|
||
|
|
ibr += n;
|
||
|
|
}
|
||
|
|
memmove(ib, ibr, ibw-ibr);
|
||
|
|
ibw = ib + (ibw-ibr);
|
||
|
|
ibr = ib;
|
||
|
|
}
|
||
|
|
if(buf == nil)
|
||
|
|
close(fd);
|
||
|
|
n = ibw-ibr;
|
||
|
|
if((n != CHK) || (memcmp(ib, "XXXXXXXXXXXXXXXX", CHK) != 0)){
|
||
|
|
fprint(2,"decrypted file failed to authenticate!\n");
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// This sends a file to the secstore disk that can, in an emergency, be
|
||
|
|
// decrypted by the program aescbc.c.
|
||
|
|
static int
|
||
|
|
putfile(SConn *conn, char *pf, uchar *buf, ulong len, uchar *key, int nkey)
|
||
|
|
{
|
||
|
|
int i, n, fd, ivo, bufi, done;
|
||
|
|
char s[Maxmsg];
|
||
|
|
uchar skey[SHA1dlen], b[CHK+Maxmsg], IV[AESbsize];
|
||
|
|
AESstate aes;
|
||
|
|
DigestState *sha;
|
||
|
|
|
||
|
|
/* create initialization vector */
|
||
|
|
srand(time(0)); /* doesn't need to be unpredictable */
|
||
|
|
for(i=0; i<AESbsize; i++)
|
||
|
|
IV[i] = 0xff & rand();
|
||
|
|
sha = sha1((uchar*)"aescbc file", 11, nil, nil);
|
||
|
|
sha1(key, nkey, skey, sha);
|
||
|
|
setupAESstate(&aes, skey, AESbsize, IV);
|
||
|
|
memset(skey, 0, sizeof skey);
|
||
|
|
|
||
|
|
snprint(s, Maxmsg, "PUT %s\n", pf);
|
||
|
|
conn->write(conn, (uchar*)s, strlen(s));
|
||
|
|
|
||
|
|
if(buf == nil){
|
||
|
|
/* get file size */
|
||
|
|
if((fd = open(pf, OREAD)) < 0){
|
||
|
|
fprint(2, "can't open %s: %r\n", pf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
len = seek(fd, 0, 2);
|
||
|
|
seek(fd, 0, 0);
|
||
|
|
} else {
|
||
|
|
fd = -1;
|
||
|
|
}
|
||
|
|
if(len > MAXFILESIZE){
|
||
|
|
fprint(2, "implausible filesize %ld for %s\n", len, pf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* send file size */
|
||
|
|
snprint(s, Maxmsg, "%ld", len+AESbsize+CHK);
|
||
|
|
conn->write(conn, (uchar*)s, strlen(s));
|
||
|
|
|
||
|
|
/* send IV and file+XXXXX in Maxmsg chunks */
|
||
|
|
ivo = AESbsize;
|
||
|
|
bufi = 0;
|
||
|
|
memcpy(b, IV, ivo);
|
||
|
|
for(done = 0; !done; ){
|
||
|
|
if(buf == nil){
|
||
|
|
n = read(fd, b+ivo, Maxmsg-ivo);
|
||
|
|
if(n < 0){
|
||
|
|
fprint(2, "read error on %s: %r\n", pf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
if((n = len - bufi) > Maxmsg-ivo)
|
||
|
|
n = Maxmsg-ivo;
|
||
|
|
memcpy(b+ivo, buf+bufi, n);
|
||
|
|
bufi += n;
|
||
|
|
}
|
||
|
|
n += ivo;
|
||
|
|
ivo = 0;
|
||
|
|
if(n < Maxmsg){ /* EOF on input; append XX... */
|
||
|
|
memset(b+n, 'X', CHK);
|
||
|
|
n += CHK; // might push n>Maxmsg
|
||
|
|
done = 1;
|
||
|
|
}
|
||
|
|
aesCBCencrypt(b, n, &aes);
|
||
|
|
if(n > Maxmsg){
|
||
|
|
assert(done==1);
|
||
|
|
conn->write(conn, b, Maxmsg);
|
||
|
|
n -= Maxmsg;
|
||
|
|
memmove(b, b+Maxmsg, n);
|
||
|
|
}
|
||
|
|
conn->write(conn, b, n);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(buf == nil)
|
||
|
|
close(fd);
|
||
|
|
fprint(2, "saved %ld bytes\n", len);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
removefile(SConn *conn, char *rf)
|
||
|
|
{
|
||
|
|
char buf[Maxmsg];
|
||
|
|
|
||
|
|
if(strchr(rf, '/')){
|
||
|
|
fprint(2, "simple filenames, not paths like %s\n", rf);
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
snprint(buf, Maxmsg, "RM %s\n", rf);
|
||
|
|
conn->write(conn, (uchar*)buf, strlen(buf));
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
cmd(AuthConn *c, char **gf, int *Gflag, char **pf, char **rf)
|
||
|
|
{
|
||
|
|
ulong len;
|
||
|
|
int rv = -1;
|
||
|
|
uchar *memfile, *memcur, *memnext;
|
||
|
|
|
||
|
|
while(*gf != nil){
|
||
|
|
if(verbose)
|
||
|
|
fprint(2, "get %s\n", *gf);
|
||
|
|
if(getfile(c->conn, *gf, *Gflag ? &memfile : nil, &len, (uchar*)c->pass, c->passlen) < 0)
|
||
|
|
goto Out;
|
||
|
|
if(*Gflag){
|
||
|
|
// write one line at a time, as required by /mnt/factotum/ctl
|
||
|
|
memcur = memfile;
|
||
|
|
while(len>0){
|
||
|
|
memnext = (uchar*)strchr((char*)memcur, '\n');
|
||
|
|
if(memnext){
|
||
|
|
write(1, memcur, memnext-memcur+1);
|
||
|
|
len -= memnext-memcur+1;
|
||
|
|
memcur = memnext+1;
|
||
|
|
}else{
|
||
|
|
write(1, memcur, len);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
free(memfile);
|
||
|
|
}
|
||
|
|
gf++;
|
||
|
|
Gflag++;
|
||
|
|
}
|
||
|
|
while(*pf != nil){
|
||
|
|
if(verbose)
|
||
|
|
fprint(2, "put %s\n", *pf);
|
||
|
|
if(putfile(c->conn, *pf, nil, 0, (uchar*)c->pass, c->passlen) < 0)
|
||
|
|
goto Out;
|
||
|
|
pf++;
|
||
|
|
}
|
||
|
|
while(*rf != nil){
|
||
|
|
if(verbose)
|
||
|
|
fprint(2, "rm %s\n", *rf);
|
||
|
|
if(removefile(c->conn, *rf) < 0)
|
||
|
|
goto Out;
|
||
|
|
rf++;
|
||
|
|
}
|
||
|
|
|
||
|
|
c->conn->write(c->conn, (uchar*)"BYE", 3);
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
Out:
|
||
|
|
c->conn->free(c->conn);
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
static int
|
||
|
|
chpasswd(AuthConn *c, char *id)
|
||
|
|
{
|
||
|
|
ulong len;
|
||
|
|
int rv = -1, newpasslen = 0;
|
||
|
|
mpint *H, *Hi;
|
||
|
|
uchar *memfile;
|
||
|
|
char *newpass, *passck;
|
||
|
|
char *list, *cur, *next, *hexHi;
|
||
|
|
char *f[8], prompt[128];
|
||
|
|
|
||
|
|
H = mpnew(0);
|
||
|
|
Hi = mpnew(0);
|
||
|
|
// changing our password is vulnerable to connection failure
|
||
|
|
for(;;){
|
||
|
|
snprint(prompt, sizeof(prompt), "new password for %s: ", id);
|
||
|
|
newpass = readcons(prompt, nil, 1);
|
||
|
|
if(newpass == nil)
|
||
|
|
goto Out;
|
||
|
|
if(strlen(newpass) >= 7)
|
||
|
|
break;
|
||
|
|
else if(strlen(newpass) == 0){
|
||
|
|
fprint(2, "!password change aborted\n");
|
||
|
|
goto Out;
|
||
|
|
}
|
||
|
|
print("!password must be at least 7 characters\n");
|
||
|
|
}
|
||
|
|
newpasslen = strlen(newpass);
|
||
|
|
snprint(prompt, sizeof(prompt), "retype password: ");
|
||
|
|
passck = readcons(prompt, nil, 1);
|
||
|
|
if(passck == nil){
|
||
|
|
fprint(2, "readcons failed\n");
|
||
|
|
goto Out;
|
||
|
|
}
|
||
|
|
if(strcmp(passck, newpass) != 0){
|
||
|
|
fprint(2, "passwords didn't match\n");
|
||
|
|
goto Out;
|
||
|
|
}
|
||
|
|
|
||
|
|
c->conn->write(c->conn, (uchar*)"CHPASS", strlen("CHPASS"));
|
||
|
|
hexHi = PAK_Hi(id, newpass, H, Hi);
|
||
|
|
c->conn->write(c->conn, (uchar*)hexHi, strlen(hexHi));
|
||
|
|
free(hexHi);
|
||
|
|
mpfree(H);
|
||
|
|
mpfree(Hi);
|
||
|
|
|
||
|
|
if(getfile(c->conn, ".", (uchar **)(void*)&list, &len, nil, 0) < 0){
|
||
|
|
fprint(2, "directory listing failed.\n");
|
||
|
|
goto Out;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Loop over files and reencrypt them; try to keep going after error */
|
||
|
|
for(cur=list; (next=strchr(cur, '\n')) != nil; cur=next+1){
|
||
|
|
*next = '\0';
|
||
|
|
if(tokenize(cur, f, nelem(f))< 1)
|
||
|
|
break;
|
||
|
|
fprint(2, "reencrypting '%s'\n", f[0]);
|
||
|
|
if(getfile(c->conn, f[0], &memfile, &len, (uchar*)c->pass, c->passlen) < 0){
|
||
|
|
fprint(2, "getfile of '%s' failed\n", f[0]);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if(putfile(c->conn, f[0], memfile, len, (uchar*)newpass, newpasslen) < 0)
|
||
|
|
fprint(2, "putfile of '%s' failed\n", f[0]);
|
||
|
|
free(memfile);
|
||
|
|
}
|
||
|
|
free(list);
|
||
|
|
c->conn->write(c->conn, (uchar*)"BYE", 3);
|
||
|
|
rv = 0;
|
||
|
|
|
||
|
|
Out:
|
||
|
|
if(newpass != nil){
|
||
|
|
memset(newpass, 0, newpasslen);
|
||
|
|
free(newpass);
|
||
|
|
}
|
||
|
|
c->conn->free(c->conn);
|
||
|
|
return rv;
|
||
|
|
}
|
||
|
|
|
||
|
|
static AuthConn*
|
||
|
|
login(char *id, char *dest, int pass_stdin, int pass_nvram)
|
||
|
|
{
|
||
|
|
AuthConn *c;
|
||
|
|
int fd, n, ntry = 0;
|
||
|
|
char *S, *PINSTA = nil, *nl, s[Maxmsg+1], *pass;
|
||
|
|
|
||
|
|
if(dest == nil){
|
||
|
|
fprint(2, "tried to login with nil dest\n");
|
||
|
|
exits("nil dest");
|
||
|
|
}
|
||
|
|
c = emalloc(sizeof(*c));
|
||
|
|
if(pass_nvram){
|
||
|
|
/* if(readnvram(&nvr, 0) < 0) */
|
||
|
|
exits("readnvram: %r");
|
||
|
|
strecpy(c->pass, c->pass+sizeof c->pass, nvr.config);
|
||
|
|
}
|
||
|
|
if(pass_stdin){
|
||
|
|
n = readn(0, s, Maxmsg-2); // so len(PINSTA)<Maxmsg-3
|
||
|
|
if(n < 1)
|
||
|
|
exits("no password on standard input");
|
||
|
|
s[n] = 0;
|
||
|
|
nl = strchr(s, '\n');
|
||
|
|
if(nl){
|
||
|
|
*nl++ = 0;
|
||
|
|
PINSTA = estrdup(nl);
|
||
|
|
nl = strchr(PINSTA, '\n');
|
||
|
|
if(nl)
|
||
|
|
*nl = 0;
|
||
|
|
}
|
||
|
|
strecpy(c->pass, c->pass+sizeof c->pass, s);
|
||
|
|
}
|
||
|
|
while(1){
|
||
|
|
if(verbose)
|
||
|
|
fprint(2, "dialing %s\n", dest);
|
||
|
|
if((fd = dial(dest, nil, nil, nil)) < 0){
|
||
|
|
fprint(2, "can't dial %s\n", dest);
|
||
|
|
free(c);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
if((c->conn = newSConn(fd)) == nil){
|
||
|
|
free(c);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
ntry++;
|
||
|
|
if(!pass_stdin && !pass_nvram){
|
||
|
|
pass = readcons("secstore password", nil, 1);
|
||
|
|
if(pass == nil)
|
||
|
|
pass = estrdup("");
|
||
|
|
if(strlen(pass) >= sizeof c->pass){
|
||
|
|
fprint(2, "password too long, skipping secstore login\n");
|
||
|
|
exits("password too long");
|
||
|
|
}
|
||
|
|
strcpy(c->pass, pass);
|
||
|
|
memset(pass, 0, strlen(pass));
|
||
|
|
free(pass);
|
||
|
|
}
|
||
|
|
if(c->pass[0]==0){
|
||
|
|
fprint(2, "null password, skipping secstore login\n");
|
||
|
|
exits("no password");
|
||
|
|
}
|
||
|
|
if(PAKclient(c->conn, id, c->pass, &S) >= 0)
|
||
|
|
break;
|
||
|
|
c->conn->free(c->conn);
|
||
|
|
if(pass_stdin)
|
||
|
|
exits("invalid password on standard input");
|
||
|
|
if(pass_nvram)
|
||
|
|
exits("invalid password in nvram");
|
||
|
|
// and let user try retyping the password
|
||
|
|
if(ntry==3)
|
||
|
|
fprint(2, "Enter an empty password to quit.\n");
|
||
|
|
}
|
||
|
|
c->passlen = strlen(c->pass);
|
||
|
|
fprint(2, "server: %s\n", S);
|
||
|
|
free(S);
|
||
|
|
if(readstr(c->conn, s) < 0){
|
||
|
|
c->conn->free(c->conn);
|
||
|
|
free(c);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
if(strcmp(s, "STA") == 0){
|
||
|
|
long sn;
|
||
|
|
if(pass_stdin){
|
||
|
|
if(PINSTA)
|
||
|
|
strncpy(s+3, PINSTA, (sizeof s)-3);
|
||
|
|
else
|
||
|
|
exits("missing PIN+SecureID on standard input");
|
||
|
|
free(PINSTA);
|
||
|
|
}else{
|
||
|
|
pass = readcons("STA PIN+SecureID", nil, 1);
|
||
|
|
if(pass == nil)
|
||
|
|
pass = estrdup("");
|
||
|
|
strncpy(s+3, pass, (sizeof s)-4);
|
||
|
|
memset(pass, 0, strlen(pass));
|
||
|
|
free(pass);
|
||
|
|
}
|
||
|
|
sn = strlen(s+3);
|
||
|
|
if(verbose)
|
||
|
|
fprint(2, "%ld\n", sn);
|
||
|
|
c->conn->write(c->conn, (uchar*)s, sn+3);
|
||
|
|
readstr(c->conn, s);
|
||
|
|
}
|
||
|
|
if(strcmp(s, "OK") != 0){
|
||
|
|
fprint(2, "%s\n", s);
|
||
|
|
c->conn->free(c->conn);
|
||
|
|
free(c);
|
||
|
|
return nil;
|
||
|
|
}
|
||
|
|
return c;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
main(int argc, char **argv)
|
||
|
|
{
|
||
|
|
int chpass = 0, pass_stdin = 0, pass_nvram = 0, rc;
|
||
|
|
int ngfile = 0, npfile = 0, nrfile = 0, Gflag[MAXFILES+1];
|
||
|
|
char *gfile[MAXFILES], *pfile[MAXFILES], *rfile[MAXFILES];
|
||
|
|
char *serve, *tcpserve, *user;
|
||
|
|
AuthConn *c;
|
||
|
|
|
||
|
|
serve = "$auth";
|
||
|
|
user = getuser();
|
||
|
|
memset(Gflag, 0, sizeof Gflag);
|
||
|
|
fmtinstall('B', mpfmt);
|
||
|
|
fmtinstall('H', encodefmt);
|
||
|
|
|
||
|
|
ARGBEGIN{
|
||
|
|
case 'c':
|
||
|
|
chpass = 1;
|
||
|
|
break;
|
||
|
|
case 'G':
|
||
|
|
Gflag[ngfile]++;
|
||
|
|
/* fall through */
|
||
|
|
case 'g':
|
||
|
|
if(ngfile >= MAXFILES)
|
||
|
|
exits("too many gfiles");
|
||
|
|
gfile[ngfile++] = ARGF();
|
||
|
|
if(gfile[ngfile-1] == nil)
|
||
|
|
usage();
|
||
|
|
break;
|
||
|
|
case 'i':
|
||
|
|
pass_stdin = 1;
|
||
|
|
break;
|
||
|
|
case 'n':
|
||
|
|
pass_nvram = 1;
|
||
|
|
break;
|
||
|
|
case 'p':
|
||
|
|
if(npfile >= MAXFILES)
|
||
|
|
exits("too many pfiles");
|
||
|
|
pfile[npfile++] = ARGF();
|
||
|
|
if(pfile[npfile-1] == nil)
|
||
|
|
usage();
|
||
|
|
break;
|
||
|
|
case 'r':
|
||
|
|
if(nrfile >= MAXFILES)
|
||
|
|
exits("too many rfiles");
|
||
|
|
rfile[nrfile++] = ARGF();
|
||
|
|
if(rfile[nrfile-1] == nil)
|
||
|
|
usage();
|
||
|
|
break;
|
||
|
|
case 's':
|
||
|
|
serve = EARGF(usage());
|
||
|
|
break;
|
||
|
|
case 'u':
|
||
|
|
user = EARGF(usage());
|
||
|
|
break;
|
||
|
|
case 'v':
|
||
|
|
verbose++;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
usage();
|
||
|
|
break;
|
||
|
|
}ARGEND;
|
||
|
|
gfile[ngfile] = nil;
|
||
|
|
pfile[npfile] = nil;
|
||
|
|
rfile[nrfile] = nil;
|
||
|
|
|
||
|
|
if(argc!=0 || user==nil)
|
||
|
|
usage();
|
||
|
|
|
||
|
|
if(chpass && (ngfile || npfile || nrfile)){
|
||
|
|
fprint(2, "Get, put, and remove invalid with password change.\n");
|
||
|
|
exits("usage");
|
||
|
|
}
|
||
|
|
|
||
|
|
rc = strlen(serve)+sizeof("tcp!!99990");
|
||
|
|
tcpserve = emalloc(rc);
|
||
|
|
if(strchr(serve,'!'))
|
||
|
|
strcpy(tcpserve, serve);
|
||
|
|
else
|
||
|
|
snprint(tcpserve, rc, "tcp!%s!5356", serve);
|
||
|
|
c = login(user, tcpserve, pass_stdin, pass_nvram);
|
||
|
|
free(tcpserve);
|
||
|
|
if(c == nil){
|
||
|
|
fprint(2, "secstore authentication failed\n");
|
||
|
|
exits("secstore authentication failed");
|
||
|
|
}
|
||
|
|
if(chpass)
|
||
|
|
rc = chpasswd(c, user);
|
||
|
|
else
|
||
|
|
rc = cmd(c, gfile, Gflag, pfile, rfile);
|
||
|
|
if(rc < 0){
|
||
|
|
fprint(2, "secstore cmd failed\n");
|
||
|
|
exits("secstore cmd failed");
|
||
|
|
}
|
||
|
|
exits("");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|