#include <u.h>#include <libc.h>#include <bio.h>#include <ndb.h> #include "ssh.h" char *cipher_names[] = { "No encryption", "IDEA", "DES", "Triple DES", "TSS", "RC4", 0}; char *auth_names[] = { "Illegal", ".rhosts or /etc/hosts.equiv", "pure RSA", "Password", ".shosts with RSA", 0}; int doabort;voiderror(char *fmt, ...) { va_list arg; char buf[2048]; va_start(arg, fmt); doprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); fprint(2, "%s: %s\n", progname, buf); if(doabort) abort(); exits("error");} /* #define DEBUG (DBG_SCP) */int DEBUG; voiddebug(int level, char *fmt, ...) { va_list arg; char buf[2048]; if (level & DEBUG) { va_start(arg, fmt); doprint(buf, buf+sizeof(buf), fmt, arg); va_end(arg); fprint(2, "%s", buf); }} voiddebugbig(int level, mpint *b, char term) { uchar buf[2048]; int s, i; if (level & DEBUG) { s = mptobe(b, buf, 1024, nil); for (i = 0; i < s; i++) fprint(2, "%2.2x", buf[i]); if (term) fprint(2, "%c", term); }} void *zalloc(int size) { void *x; /* allocate and set to zero */ if ((x = mallocz(size, 1)) == 0) error("malloc"); setmalloctag(x, getcallerpc(&size)); return x;} void *mmalloc(int size) { void *x; x = zalloc(size); setmalloctag(x, getcallerpc(&size)); return x;} voidmfree(Packet *packet) { debug(DBG_PACKET, "Remaining Length: %d\n", packet->length); free(packet);} voidprintbig(int fd, mpint *b, int base, char term){ char *p; p = mptoa(b, base, nil, 0); if(term) fprint(fd, "%s%c", p, term); else fprint(fd, "%s", p); free(p);} voidprintpublickey(int fd, RSApub *key) { fprint(fd, "%d ", mpsignif(key->n)); printbig(fd, key->ek, 16, ' '); printbig(fd, key->n, 16, '\n');} voidprintdecpublickey(int fd, RSApub *key) { fprint(fd, "%d ", mpsignif(key->n)); printbig(fd, key->ek, 10, ' '); printbig(fd, key->n, 10, '\n');} intreadpublickey(FILE *f, RSApub *key) { char buf[2048]; char *p; mpint *ek, *n; if (fgets(buf, 2048, f) == nil) return 0; /* * hostname size exponent modulus * but the hostname gets cut out before we get called. */ ek = n = nil; if((p = strchr(buf, ' ')) == nil || (ek=strtomp(p, &p, 16, key->ek)) == nil || (n=strtomp(p, &p, 16, key->n)) == nil){ if(ek != key->ek) mpfree(ek); if(n != key->n) mpfree(n); return 0; } key->ek = ek; key->n = n; return 1;} voidprintsecretkey(int fd, RSApriv *key) { fprint(fd, "%d ", mpsignif(key->pub.n)); printbig(fd, key->pub.ek, 16, ' '); printbig(fd, key->dk, 16, ' '); printbig(fd, key->pub.n, 16, ' '); printbig(fd, key->p, 16, ' '); printbig(fd, key->q, 16, ' '); printbig(fd, key->kp, 16, ' '); printbig(fd, key->kq, 16, ' '); printbig(fd, key->c2, 16, '\n');} intreadsecretkey(FILE *f, RSApriv *key) { char buf[2048]; char *p; mpint *ek, *dk, *n, *pp, *q, *kp, *kq, *c2; if (fgets(buf, 2048, f) == nil) return 0; /* * size ek dk n p q kp kq c2 */ ek = dk = n = pp = q = kp = kq = c2 = nil; if((p = strchr(buf, ' ')) == nil || (ek=strtomp(p, &p, 16, key->pub.ek)) == nil || (dk=strtomp(p, &p, 16, key->dk)) == nil || (n=strtomp(p, &p, 16, key->pub.n)) == nil || (pp=strtomp(p, &p, 16, key->p)) == nil || (q=strtomp(p, &p, 16, key->q)) == nil || (kp=strtomp(p, &p, 16, key->kp)) == nil || (kq=strtomp(p, &p, 16, key->kq)) == nil || (c2=strtomp(p, &p, 16, key->c2)) == nil){ if(ek != key->pub.ek) mpfree(ek); if(dk != key->dk) mpfree(dk); if(n != key->pub.n) mpfree(n); if(pp != key->p) mpfree(pp); if(q != key->q) mpfree(q); if(kp != key->p) mpfree(kp); if(kq != key->q) mpfree(kq); if(c2 != key->c2) mpfree(c2); return 0; } key->pub.ek = ek; key->dk = dk; key->pub.n = n; key->p = pp; key->q = q; key->kp = kp; key->kq = kq; key->c2 = c2; return 1;} voidcomp_sess_id(mpint *m1, mpint *m2, uchar *cookie, uchar *sid) { uchar sess_str[1024]; int bytes; bytes = mptobe(m1, sess_str, sizeof(sess_str)-8, nil); bytes += mptobe(m2, sess_str + bytes, sizeof(sess_str)-8-bytes, nil); memcpy(sess_str + bytes, cookie, 8); md5(sess_str, bytes+8, sid, 0);} voidRSApad(uchar *inbuf, int inbytes, uchar *outbuf, int outbytes) { uchar *p, *q; uchar x; debug(DBG_CRYPTO, "Padding a %d-byte number to %d bytes\n", inbytes, outbytes); assert(outbytes >= inbytes+3); p = &inbuf[inbytes-1]; q = &outbuf[outbytes-1]; while (p >= inbuf) *q-- = *p--; *q-- = 0; while (q >= outbuf+2) { while ((x = nrand(0x100)) == 0) ; *q-- = x; } outbuf[0] = 0; outbuf[1] = 2;} mpint*RSAunpad(mpint *bin, int bytes) { int n; uchar buf[256]; mpint *bout; bout = mpnew(0); setmalloctag(bout, getcallerpc(&bin)); n = mptobe(bin, buf, 256, nil); if (buf[0] != 2) error("RSAunpad"); betomp(buf+n-bytes, bytes, bout); return bout;} mpint*RSAEncrypt(mpint *in, RSApub *rsa){ mpint *out; out = rsaencrypt(rsa, in, nil); mpfree(in); return out;} mpint*RSADecrypt(mpint *in, RSApriv *rsa){ mpint *out; out = rsadecrypt(rsa, in, nil); setmalloctag(out, getcallerpc(&in)); mpfree(in); return out;} intverify_key(char *host, RSApub *received_key, char *keyring) { FILE *f; RSApub *file_key; char s[2048], *p; int c; /* Return values: key_ok, key_wrong, key_notfound, key_file */ if ((f = fopen(keyring, "r")) == nil) { debug(DBG_AUTH, "Can't open %s: %r\n", keyring); return key_file; } for (;;) { p = s; while ((c = fgetc(f)) != '\n') { if (c == EOF) { fclose(f); return key_notfound; } if (p == s && c == '#') { fgets(s, 2048, f); break; } if (c == ' ' || c == '\t') { *p = 0; if (strcmp(s, host)) { debug(DBG_AUTH, "wrong host %s\n", s); fgets(s, 2048, f); break; } debug(DBG_AUTH, "host found: %s\n", s); file_key = rsapuballoc(); if (readpublickey(f, file_key) == 0) { debug(DBG_AUTH, "Can't read key\n"); fclose(f); rsapubfree(file_key); return key_file; } if (mpcmp(file_key->n, received_key->n) || mpcmp(file_key->ek, received_key->ek)) { debug(DBG_AUTH, "wrong key\n", s); fclose(f); rsapubfree(file_key); return key_wrong; } fclose(f); rsapubfree(file_key); return key_ok; } *p++ = c; } } debug(DBG_AUTH, "Host not found\n"); fclose(f); return key_notfound;} intreplace_key(char *host, RSApub *received_key, char *keyring) { FILE *f; int fd; char s[1024], keyringnew[256], *p; int i, done; Dir dir; /* Return values: key_ok, key_file */ if ((f = fopen(keyring, "r")) == nil) { debug(DBG_AUTH, "Can't open %s: %r\n", keyring); return key_file; } snprint(keyringnew, sizeof(keyringnew), "%s.new", keyring); if ((fd = create(keyringnew, OWRITE|OTRUNC, 0644)) < 0) { debug(DBG_AUTH, "Can't open %s: %r\n", keyringnew); fclose(f); return key_file; } done = 0; while (fgets(s, sizeof(s), f)) { i = strcspn(s, " \t\n"); if (strlen(host) == i && strncmp(s, host, i) == 0) { if (done == 0) { fprint(fd, "%s ", host); printpublickey(fd, received_key); done = 1; } } else { write(fd, s, strlen(s)); } } if (done == 0) { fprint(fd, "%s ", host); printpublickey(fd, received_key); } fclose(f); remove(keyring); dirfstat(fd, &dir); p = strrchr(dir.name, '.'); if (p == 0) error("There's something rotten in the State of Denmark"); *p = 0; dirfwstat(fd, &dir); close(fd); return key_ok;} intisatty(int fd) { Dir d1, d2; if(dirfstat(fd, &d1)==-1) return 0; if(dirstat("/dev/cons", &d2)==-1) return 0; return d1.type==d2.type&&d1.dev==d2.dev&&d1.qid.path==d2.qid.path;} voidgetdomainname(char *name, char *dest, int len) { char *attr[1]; Ndbtuple *t; snprint(dest, len, "%s", name); attr[0] = "dom"; t = csipinfo(nil, ipattr(name), name, attr, 1); if(t != nil){ snprint(dest, len, "%s", t->val); ndbfree(t); }} /* * convert b into a big-endian array of bytes, right justified in buf */voidmptobuf(mpint *b, uchar *buf, int len){ int n; n = mptobe(b, buf, len, nil); assert(n >= 0); if(n < len){ len -= n; memmove(buf+len, buf, n); memset(buf, 0, len); }}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>
#include "ssh.h"
char *cipher_names[] = {
"No encryption",
"IDEA",
"DES",
"Triple DES",
"TSS",
"RC4",
0
};
char *auth_names[] = {
"Illegal",
".rhosts or /etc/hosts.equiv",
"pure RSA",
"Password",
".shosts with RSA",
0
};
int doabort;
void
error(char *fmt, ...) {
va_list arg;
char buf[2048];
va_start(arg, fmt);
doprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
fprint(2, "%s: %s\n", progname, buf);
if(doabort)
abort();
exits("error");
}
/* #define DEBUG (DBG_SCP) */
int DEBUG;
void
debug(int level, char *fmt, ...) {
va_list arg;
char buf[2048];
if (level & DEBUG) {
va_start(arg, fmt);
doprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
fprint(2, "%s", buf);
}
}
void
debugbig(int level, mpint *b, char term) {
uchar buf[2048];
int s, i;
if (level & DEBUG) {
s = mptobe(b, buf, 1024, nil);
for (i = 0; i < s; i++)
fprint(2, "%2.2x", buf[i]);
if (term)
fprint(2, "%c", term);
}
}
void *
zalloc(int size) {
void *x;
/* allocate and set to zero */
if ((x = mallocz(size, 1)) == 0)
error("malloc");
setmalloctag(x, getcallerpc(&size));
return x;
}
void *
mmalloc(int size) {
void *x;
x = zalloc(size);
setmalloctag(x, getcallerpc(&size));
return x;
}
void
mfree(Packet *packet) {
debug(DBG_PACKET, "Remaining Length: %d\n", packet->length);
free(packet);
}
void
printbig(int fd, mpint *b, int base, char term)
{
char *p;
p = mptoa(b, base, nil, 0);
if(term)
fprint(fd, "%s%c", p, term);
else
fprint(fd, "%s", p);
free(p);
}
void
printpublickey(int fd, RSApub *key) {
fprint(fd, "%d ", mpsignif(key->n));
printbig(fd, key->ek, 16, ' ');
printbig(fd, key->n, 16, '\n');
}
void
printdecpublickey(int fd, RSApub *key) {
fprint(fd, "%d ", mpsignif(key->n));
printbig(fd, key->ek, 10, ' ');
printbig(fd, key->n, 10, '\n');
}
int
readpublickey(FILE *f, RSApub *key) {
char buf[2048];
char *p;
mpint *ek, *n;
if (fgets(buf, 2048, f) == nil)
return 0;
/*
* hostname size exponent modulus
* but the hostname gets cut out before we get called.
*/
ek = n = nil;
if((p = strchr(buf, ' ')) == nil
|| (ek=strtomp(p, &p, 16, key->ek)) == nil
|| (n=strtomp(p, &p, 16, key->n)) == nil){
if(ek != key->ek)
mpfree(ek);
if(n != key->n)
mpfree(n);
return 0;
}
key->ek = ek;
key->n = n;
return 1;
}
void
printsecretkey(int fd, RSApriv *key) {
fprint(fd, "%d ", mpsignif(key->pub.n));
printbig(fd, key->pub.ek, 16, ' ');
printbig(fd, key->dk, 16, ' ');
printbig(fd, key->pub.n, 16, ' ');
printbig(fd, key->p, 16, ' ');
printbig(fd, key->q, 16, ' ');
printbig(fd, key->kp, 16, ' ');
printbig(fd, key->kq, 16, ' ');
printbig(fd, key->c2, 16, '\n');
}
int
readsecretkey(FILE *f, RSApriv *key) {
char buf[2048];
char *p;
mpint *ek, *dk, *n, *pp, *q, *kp, *kq, *c2;
if (fgets(buf, 2048, f) == nil)
return 0;
/*
* size ek dk n p q kp kq c2
*/
ek = dk = n = pp = q = kp = kq = c2 = nil;
if((p = strchr(buf, ' ')) == nil
|| (ek=strtomp(p, &p, 16, key->pub.ek)) == nil
|| (dk=strtomp(p, &p, 16, key->dk)) == nil
|| (n=strtomp(p, &p, 16, key->pub.n)) == nil
|| (pp=strtomp(p, &p, 16, key->p)) == nil
|| (q=strtomp(p, &p, 16, key->q)) == nil
|| (kp=strtomp(p, &p, 16, key->kp)) == nil
|| (kq=strtomp(p, &p, 16, key->kq)) == nil
|| (c2=strtomp(p, &p, 16, key->c2)) == nil){
if(ek != key->pub.ek)
mpfree(ek);
if(dk != key->dk)
mpfree(dk);
if(n != key->pub.n)
mpfree(n);
if(pp != key->p)
mpfree(pp);
if(q != key->q)
mpfree(q);
if(kp != key->p)
mpfree(kp);
if(kq != key->q)
mpfree(kq);
if(c2 != key->c2)
mpfree(c2);
return 0;
}
key->pub.ek = ek;
key->dk = dk;
key->pub.n = n;
key->p = pp;
key->q = q;
key->kp = kp;
key->kq = kq;
key->c2 = c2;
return 1;
}
void
comp_sess_id(mpint *m1, mpint *m2, uchar *cookie, uchar *sid) {
uchar sess_str[1024];
int bytes;
bytes = mptobe(m1, sess_str, sizeof(sess_str)-8, nil);
bytes += mptobe(m2, sess_str + bytes, sizeof(sess_str)-8-bytes, nil);
memcpy(sess_str + bytes, cookie, 8);
md5(sess_str, bytes+8, sid, 0);
}
void
RSApad(uchar *inbuf, int inbytes, uchar *outbuf, int outbytes) {
uchar *p, *q;
uchar x;
debug(DBG_CRYPTO, "Padding a %d-byte number to %d bytes\n",
inbytes, outbytes);
assert(outbytes >= inbytes+3);
p = &inbuf[inbytes-1];
q = &outbuf[outbytes-1];
while (p >= inbuf) *q-- = *p--;
*q-- = 0;
while (q >= outbuf+2) {
while ((x = nrand(0x100)) == 0)
;
*q-- = x;
}
outbuf[0] = 0;
outbuf[1] = 2;
}
mpint*
RSAunpad(mpint *bin, int bytes) {
int n;
uchar buf[256];
mpint *bout;
bout = mpnew(0);
setmalloctag(bout, getcallerpc(&bin));
n = mptobe(bin, buf, 256, nil);
if (buf[0] != 2)
error("RSAunpad");
betomp(buf+n-bytes, bytes, bout);
return bout;
}
mpint*
RSAEncrypt(mpint *in, RSApub *rsa)
{
mpint *out;
out = rsaencrypt(rsa, in, nil);
mpfree(in);
return out;
}
mpint*
RSADecrypt(mpint *in, RSApriv *rsa)
{
mpint *out;
out = rsadecrypt(rsa, in, nil);
setmalloctag(out, getcallerpc(&in));
mpfree(in);
return out;
}
int
verify_key(char *host, RSApub *received_key, char *keyring) {
FILE *f;
RSApub *file_key;
char s[2048], *p;
int c;
/* Return values: key_ok, key_wrong, key_notfound, key_file */
if ((f = fopen(keyring, "r")) == nil) {
debug(DBG_AUTH, "Can't open %s: %r\n", keyring);
return key_file;
}
for (;;) {
p = s;
while ((c = fgetc(f)) != '\n') {
if (c == EOF) {
fclose(f);
return key_notfound;
}
if (p == s && c == '#') {
fgets(s, 2048, f);
break;
}
if (c == ' ' || c == '\t') {
*p = 0;
if (strcmp(s, host)) {
debug(DBG_AUTH, "wrong host %s\n", s);
fgets(s, 2048, f);
break;
}
debug(DBG_AUTH, "host found: %s\n", s);
file_key = rsapuballoc();
if (readpublickey(f, file_key) == 0) {
debug(DBG_AUTH, "Can't read key\n");
fclose(f);
rsapubfree(file_key);
return key_file;
}
if (mpcmp(file_key->n, received_key->n) ||
mpcmp(file_key->ek, received_key->ek)) {
debug(DBG_AUTH, "wrong key\n", s);
fclose(f);
rsapubfree(file_key);
return key_wrong;
}
fclose(f);
rsapubfree(file_key);
return key_ok;
}
*p++ = c;
}
}
debug(DBG_AUTH, "Host not found\n");
fclose(f);
return key_notfound;
}
int
replace_key(char *host, RSApub *received_key, char *keyring) {
FILE *f;
int fd;
char s[1024], keyringnew[256], *p;
int i, done;
Dir dir;
/* Return values: key_ok, key_file */
if ((f = fopen(keyring, "r")) == nil) {
debug(DBG_AUTH, "Can't open %s: %r\n", keyring);
return key_file;
}
snprint(keyringnew, sizeof(keyringnew), "%s.new", keyring);
if ((fd = create(keyringnew, OWRITE|OTRUNC, 0644)) < 0) {
debug(DBG_AUTH, "Can't open %s: %r\n", keyringnew);
fclose(f);
return key_file;
}
done = 0;
while (fgets(s, sizeof(s), f)) {
i = strcspn(s, " \t\n");
if (strlen(host) == i && strncmp(s, host, i) == 0) {
if (done == 0) {
fprint(fd, "%s ", host);
printpublickey(fd, received_key);
done = 1;
}
} else {
write(fd, s, strlen(s));
}
}
if (done == 0) {
fprint(fd, "%s ", host);
printpublickey(fd, received_key);
}
fclose(f);
remove(keyring);
dirfstat(fd, &dir);
p = strrchr(dir.name, '.');
if (p == 0) error("There's something rotten in the State of Denmark");
*p = 0;
dirfwstat(fd, &dir);
close(fd);
return key_ok;
}
int
isatty(int fd) {
Dir d1, d2;
if(dirfstat(fd, &d1)==-1) return 0;
if(dirstat("/dev/cons", &d2)==-1) return 0;
return d1.type==d2.type&&d1.dev==d2.dev&&d1.qid.path==d2.qid.path;
}
void
getdomainname(char *name, char *dest, int len) {
char *attr[1];
Ndbtuple *t;
snprint(dest, len, "%s", name);
attr[0] = "dom";
t = csipinfo(nil, ipattr(name), name, attr, 1);
if(t != nil){
snprint(dest, len, "%s", t->val);
ndbfree(t);
}
}
/*
* convert b into a big-endian array of bytes, right justified in buf
*/
void
mptobuf(mpint *b, uchar *buf, int len)
{
int n;
n = mptobe(b, buf, len, nil);
assert(n >= 0);
if(n < len){
len -= n;
memmove(buf+len, buf, n);
memset(buf, 0, len);
}
}