Commit 83b3d5d3 authored by Leigh Stoller's avatar Leigh Stoller

Checkpoint widearea changes; add privkey support. Right now we

take the key and verify it, but do not require that it be sent.
We can make it required later.
parent 66aa173f
......@@ -4,9 +4,10 @@
* All rights reserved.
*/
#define TBSERVER_PORT 7777
#define TBSERVER_PORT2 14443
#define MYBUFSIZE 2048
#define TBSERVER_PORT 7777
#define TBSERVER_PORT2 14443
#define MYBUFSIZE 2048
#define BOSSNODE_FILENAME "bossnode"
/*
* As the tmcd changes, incompatable changes with older version of
......
......@@ -28,18 +28,22 @@
#include "config.h"
#endif
#ifndef STANDALONE
#undef BOSSNODE
#endif
#ifdef BOSSNODE
#define DEFAULT_BOSSNODE BOSSNODE
#else
#define DEFAULT_BOSSNODE NULL
#endif
#ifndef BOSSNODEFILE
#define BOSSNODEFILE "/usr/local/etc/testbed/bossnode"
#undef BOSSNODE
#ifndef KEYFILE
#define KEYFILE "/etc/emulab.pkey"
#endif
/*
* We search a couple of dirs for the bossnode file.
*/
static char *bossnodedirs[] = {
"/etc/testbed",
"/etc/rc.d/testbed",
"/usr/local/etc/testbed",
"/usr/local/etc/emulab",
0
};
/*
* Need to try several ports cause of firewalling.
*/
......@@ -61,6 +65,7 @@ char *usagestr =
" -p portnum Specify a port number to connect to\n"
" -v versnum Specify a version number for tmcd\n"
" -n vnodeid Specify the vnodeid\n"
" -k keyfile Specify the private keyfile\n"
" -u Use UDP instead of TCP\n"
" -t timeout Timeout waiting for the controller.\n"
"\n";
......@@ -81,10 +86,13 @@ main(int argc, char **argv)
struct hostent *he;
struct in_addr serverip;
char buf[MYBUFSIZE], *bp, *response = "";
char *bossnode = DEFAULT_BOSSNODE;
char *bossnode = NULL;
int version = CURRENT_VERSION;
char *vnodeid = NULL;
char *keyfile = NULL;
char *privkey = NULL;
int waitfor = 0;
FILE *fp;
#ifdef UDP
int useudp = 0;
#endif
......@@ -101,6 +109,9 @@ main(int argc, char **argv)
case 'n':
vnodeid = optarg;
break;
case 'k':
keyfile = optarg;
break;
case 'v':
version = atoi(optarg);
break;
......@@ -126,20 +137,30 @@ main(int argc, char **argv)
* How do we find our bossnode?
*
* 1. Command line.
* 2. Compiled in.
* 3. /usr/local/etc/bossnode
* 4. nameserver goo below.
* 2. From a file in the list above.
* 3. nameserver goo below.
*/
if (!bossnode) {
FILE *fp;
if ((fp = fopen(BOSSNODEFILE, "r")) != NULL) {
if (fgets(buf, sizeof(buf), fp)) {
if ((bp = strchr(buf, '\n')))
*bp = (char) NULL;
bossnode = strdup(buf);
/*
* Search for the file.
*/
char **cp = bossnodedirs;
while (*cp) {
sprintf(buf, "%s/%s", *cp, BOSSNODE_FILENAME);
if (access(buf, R_OK) == 0)
break;
cp++;
}
if (*cp) {
if ((fp = fopen(buf, "r")) != NULL) {
if (fgets(buf, sizeof(buf), fp)) {
if ((bp = strchr(buf, '\n')))
*bp = (char) NULL;
bossnode = strdup(buf);
}
fclose(fp);
}
fclose(fp);
}
}
if (!bossnode)
......@@ -152,6 +173,28 @@ main(int argc, char **argv)
exit(1);
}
/*
* Grab the key. Its not an error if we do not find it.
*/
if (keyfile) {
/* Well, if one was specifed it has to exist. */
if (access(keyfile, R_OK) < 0) {
perror("keyfile");
exit(1);
}
}
else
keyfile = KEYFILE;
if ((fp = fopen(keyfile, "r")) != NULL) {
if (fgets(buf, sizeof(buf), fp)) {
if ((bp = strchr(buf, '\n')))
*bp = (char) NULL;
privkey = strdup(buf);
}
fclose(fp);
}
if (waitfor) {
alarm(waitfor);
}
......@@ -226,6 +269,11 @@ main(int argc, char **argv)
sprintf(&buf[strlen(buf)], "VNODEID=%s ", vnodeid);
}
/* Tack on privkey */
if (privkey) {
sprintf(&buf[strlen(buf)], "PRIVKEY=%s ", privkey);
}
/*
* Since we've gone through a getopt() pass, argv[0] is now the
* first argument
......
......@@ -66,6 +66,7 @@ static int iptonodeid(struct in_addr, char *,char *,char *,char *,int *);
static int nodeidtonickname(char *nodeid, char *nickname);
static int nodeidtocontrolnet(char *nodeid, int *net);
static int checkdbredirect(char *nodeid);
static int checkprivkey(struct in_addr, char *);
static void tcpserver(int sock);
static void udpserver(int sock);
static int handle_request(int, struct sockaddr_in *, char *, int);
......@@ -262,6 +263,9 @@ main(int argc, char **argv)
fgets(fshostid, HOSTID_SIZE, fp);
if (rindex(fshostid, '\n')) {
*rindex(fshostid, '\n') = 0;
if (debug) {
info("fshostid: %s\n", fshostid);
}
}
else {
error("fshostid from %s may be corrupt: %s",
......@@ -489,11 +493,12 @@ static int
handle_request(int sock, struct sockaddr_in *client, char *rdata, int istcp)
{
struct sockaddr_in redirect_client;
int redirect = 0, isvnode = 0;
int redirect = 0, isvnode = 0, havekey = 0;
char buf[BUFSIZ], *bp, *cp;
char nodeid[TBDB_FLEN_NODEID];
char vnodeid[TBDB_FLEN_NODEID];
char class[TBDB_FLEN_NODECLASS];
char privkey[TBDB_FLEN_PRIVKEY];
char type[TBDB_FLEN_NODETYPE];
int i, islocal, err = 0;
int version = DEFAULT_VERSION;
......@@ -503,6 +508,20 @@ handle_request(int sock, struct sockaddr_in *client, char *rdata, int istcp)
*/
bp = rdata;
while ((bp = strsep(&rdata, " ")) != NULL) {
/*
* Look for PRIVKEY.
*/
if (sscanf(bp, "PRIVKEY=%64s", buf)) {
havekey = 1;
strncpy(privkey, buf, sizeof(privkey));
if (debug) {
info("PRIVKEY %s\n", buf);
}
continue;
}
/*
* Look for VERSION.
*/
......@@ -651,6 +670,26 @@ handle_request(int sock, struct sockaddr_in *client, char *rdata, int istcp)
goto skipit;
}
/*
* Do private key check. widearea nodes must report a private key
* It comes over ssl of course. At present we skip this check for
* ron nodes.
*/
if (!islocal) {
if (!havekey) {
error("%s: No privkey sent!\n", nodeid);
/*
* Skip. Okay, the problem is that the nodes out
* there are not reporting the key!
goto skipit;
*/
}
else if (checkprivkey(client->sin_addr, privkey)) {
error("%s: privkey mismatch: %s!\n", nodeid, privkey);
goto skipit;
}
}
/*
* Figure out what command was given.
*/
......@@ -2297,9 +2336,10 @@ COMMAND_PROTOTYPE(dosfshostid)
signal(SIGALRM, dosfshostiddead);
alarm(1);
unlink(dspath);
if (symlink(sfspath, dspath) < 0)
if (unlink(dspath) < 0 ||
symlink(sfspath, dspath) < 0) {
sfshostiddeadfl = 1;
}
}
alarm(0);
if (sfshostiddeadfl) {
......@@ -3217,6 +3257,37 @@ checkdbredirect(char *nodeid)
return 0;
}
/*
* Check private key.
*/
static int
checkprivkey(struct in_addr ipaddr, char *privkey)
{
MYSQL_RES *res;
MYSQL_ROW row;
res = mydb_query("select privkey from widearea_privkeys "
"where IP='%s'",
1, inet_ntoa(ipaddr));
if (!res) {
error("checkprivkey: %s: DB Error getting privkey!\n",
inet_ntoa(ipaddr));
return 1;
}
if (! (int)mysql_num_rows(res)) {
mysql_free_result(res);
return 1;
}
row = mysql_fetch_row(res);
mysql_free_result(res);
if (! row[0] || !row[0][0])
return 1;
return strcmp(privkey, row[0]);
}
#ifdef EVENTSYS
/*
* Connect to the event system. It's not an error to call this function if
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment