diff --git a/tmcd/tmcd.c b/tmcd/tmcd.c index 57dd1919586e91f12cc267227377dd635368f58e..40074259a2a160456690c969179a07f8e383a1b8 100644 --- a/tmcd/tmcd.c +++ b/tmcd/tmcd.c @@ -173,6 +173,7 @@ int mydb_update(char *query, ...); static int safesymlink(char *name1, char *name2); static int getImageInfo(char *path, char *nodeid, char *pid, char *imagename, unsigned int *mtime, unsigned int *chunks); +static int getrandomchars(char *buf, int len); /* socket timeouts */ static int readtimo = READTIMO; @@ -7354,38 +7355,17 @@ COMMAND_PROTOTYPE(doisalive) */ COMMAND_PROTOTYPE(doipodinfo) { - char buf[MYBUFSIZE], *bp; - unsigned char randdata[16], hashbuf[16*2+1]; - int fd, cc, i; + char buf[MYBUFSIZE], hashbuf[BUFSIZ]; if (!tcp) { error("IPODINFO: %s: Cannot do this in UDP mode!\n", reqp->nodeid); return 1; } - - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { - errorc("opening /dev/urandom"); - return 1; - } - if ((cc = read(fd, randdata, sizeof(randdata))) < 0) { - errorc("reading /dev/urandom"); - close(fd); + if (getrandomchars(hashbuf, 32)) { + error("IPODINFO: no random chars for password\n"); return 1; } - if (cc != sizeof(randdata)) { - error("Short read from /dev/urandom: %d", cc); - close(fd); - return 1; - } - close(fd); - - bp = (char *)hashbuf; - for (i = 0; i < sizeof(randdata); i++) { - bp += sprintf(bp, "%02x", randdata[i]); - } - *bp = '\0'; - mydb_update("update nodes set ipodhash='%s' " "where node_id='%s'", hashbuf, reqp->nodeid); @@ -7679,6 +7659,38 @@ COMMAND_PROTOTYPE(dojailconfig) mysql_free_result(res); } + /* + * Per jail root password hash if one has been set. + */ + res = mydb_query("select attrvalue from node_attributes " + " where node_id='%s' and " + " attrkey='root_password'", + 1, reqp->nodeid); + + if (!res) { + error("JAILCONFIG: %s: DB Error getting root_password.\n", + reqp->nodeid); + return 1; + } + if ((nrows = (int)mysql_num_rows(res))) { + row = mysql_fetch_row(res); + if (row[0] && row[0][0]) { + char saltbuf[BUFSIZ], *bp; + + if (getrandomchars(saltbuf, 8) != 0) { + snprintf(saltbuf, sizeof(saltbuf), + "%ud", time(NULL)); + } + sprintf(buf, "$1$%s", saltbuf); + bp = crypt(row[0], buf); + + bufp = buf; + bufp += OUTPUT(bufp, ebufp - bufp, "ROOTHASH=%s\n", bp); + client_writeback(sock, buf, strlen(buf), tcp); + } + } + mysql_free_result(res); + /* * Now return the IP interface list that this jail has access to. * These are tunnels or ip aliases on the real interfaces, but @@ -9489,43 +9501,33 @@ COMMAND_PROTOTYPE(dorootpswd) { MYSQL_RES *res; MYSQL_ROW row; - char buf[MYBUFSIZE], hashbuf[MYBUFSIZE], *bp; + char buf[BUFSIZ], hashbuf[BUFSIZ], saltbuf[BUFSIZ], *bp; + char *nodeid = reqp->pnodeid; + + /* + * On a virtnode, we return the password for the physical + * host, but not on a shared node, it needs its own. + */ + if (reqp->isvnode && reqp->sharing_mode[0]) { + nodeid = reqp->nodeid; + } res = mydb_query("select attrvalue from node_attributes " " where node_id='%s' and " " attrkey='root_password'", - 1, reqp->pnodeid); + 1, nodeid); if (!res || (int)mysql_num_rows(res) == 0) { - unsigned char randdata[5]; - int fd, cc, i; - - if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { - errorc("opening /dev/urandom"); - return 1; - } - if ((cc = read(fd, randdata, sizeof(randdata))) < 0) { - errorc("reading /dev/urandom"); - close(fd); - return 1; - } - if (cc != sizeof(randdata)) { - error("Short read from /dev/urandom: %d", cc); - close(fd); + if (getrandomchars(hashbuf, 12)) { + error("DOROOTPSWD: no random chars for password\n"); + if (res) + mysql_free_result(res); return 1; } - close(fd); - - bp = hashbuf; - for (i = 0; i < sizeof(randdata); i++) { - bp += sprintf(bp, "%02x", randdata[i]); - } - *bp = '\0'; - mydb_update("replace into node_attributes set " " node_id='%s', " " attrkey='root_password',attrvalue='%s'", - reqp->nodeid, hashbuf); + nodeid, hashbuf); } else { row = mysql_fetch_row(res); @@ -9538,7 +9540,11 @@ COMMAND_PROTOTYPE(dorootpswd) * Need to crypt() this for the node since we obviously do not want * to return the plain text. */ - sprintf(buf, "$1$%s", hashbuf); + if (getrandomchars(saltbuf, 8)) { + error("DOROOTPSWD: no random chars for salt\n"); + return 1; + } + sprintf(buf, "$1$%s", saltbuf); bp = crypt(hashbuf, buf); OUTPUT(buf, sizeof(buf), "HASH=%s\n", bp); @@ -12488,3 +12494,35 @@ COMMAND_PROTOTYPE(dotiplineinfo) return 0; } +static int +getrandomchars(char *buf, int len) +{ + unsigned char randdata[MYBUFSIZE]; + int fd, cc, i; + char *bp; + + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + errorc("opening /dev/urandom"); + return 1; + } + if ((cc = read(fd, randdata, len)) < 0) { + errorc("reading /dev/urandom"); + close(fd); + return 1; + } + if (cc != len) { + error("Short read from /dev/urandom: %d", len); + close(fd); + return 1; + } + bp = buf; + for (i = 0; i < len;) { + cc = sprintf(bp, "%02x", randdata[i]); + i += cc; + bp += cc; + } + buf[len] = '\0'; + + close(fd); + return 0; +}