From 7bd23eea29c3ba607649eddd023e2ca173d01b56 Mon Sep 17 00:00:00 2001 From: konrad Date: Sat, 1 Mar 2008 14:45:07 +0000 Subject: [PATCH] add host management git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@98 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- doc/prog_protocol.html | 24 ++++++ src/host.cpp | 120 ++++++++++++++++++++++++++++ src/host.h | 59 ++++++++++++++ src/keygen.cpp | 6 ++ src/keygen.h | 1 + src/mainwindow.cpp | 33 ++++++-- src/mainwindow.h | 2 +- src/overview.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++++- src/overview.h | 15 ++++ src/smoke.pro | 2 + src/webrequest.cpp | 32 +++++++- src/webrequest.h | 7 ++ www/inc/machine/host.php | 100 +++++++++++++++++++++++ www/machine.php | 34 +++++++-- 14 files changed, 612 insertions(+), 18 deletions(-) create mode 100644 src/host.cpp create mode 100644 src/host.h create mode 100644 www/inc/machine/host.php diff --git a/doc/prog_protocol.html b/doc/prog_protocol.html index e296e47..1b7ca1a 100644 --- a/doc/prog_protocol.html +++ b/doc/prog_protocol.html @@ -313,3 +313,27 @@ All setable hosts must be listed, so that the client can use these for displayin The setuserhosts transaction can be used to update a users allowed client hosts. The request is identical to the response of getuserhosts, while the response is an empty document on success - only the status "OK" counts.

Any host listed in the request is changed accordingly, non-existant hosts are ignored, hosts not listed are left unchanged.

+ +

Creating and Changing Hosts

+ +The addhost transaction creates new hosts. The sethost transaction changes the key of existing hosts. For both the request looks like:

+ +

+<Hosts>
+  <Host name="hostname">hostkey</Host>
+  ...
+</Hosts>
+
+ +FIXME: currently these transactions do not return any feedback about success. The sethost transaction silently ignores hosts that do not exist. + +

Getting All Hosts

+ +The gethosts transaction returns the name and key of all hosts. There is no request body. The response looks like the request above. + +

Deleting Hosts

+ +The deletehost transaction deletes one single host. The request contains only the name of the host as ASCII text.

+ +FIXME: special hosts (beginning with "_") return errors. Non-existing hosts are silently ignored. + diff --git a/src/host.cpp b/src/host.cpp new file mode 100644 index 0000000..f934b07 --- /dev/null +++ b/src/host.cpp @@ -0,0 +1,120 @@ +// +// C++ Implementation: host +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "host.h" +#include "webrequest.h" +#include "keygen.h" + +#include +#include +#include + +MHost::MHost(MWebRequest*r,QDomElement&e) +{ + req=r; + m_hostid=e.attribute("name").trimmed(); + m_key=e.text().trimmed(); +} + +MHost::MHost(MWebRequest*r,QString n,QString k) +{ + req=r; + m_hostid=n; + m_key=k; +} + +MHost::MHost() +{ + req=0; +} + +MHost::MHost(const MHost&u) +{ + req=u.req; + m_hostid=u.m_hostid; + m_key=u.m_key; +} + +QString MHost::hostId() +{ + return m_hostid; +} + +QString MHost::hostKey() +{ + return m_key; +} + +bool MHost::isValid() +{ + return QRegExp("[A-Za-z0-9_]+").exactMatch(m_hostid); +} + +int MHost::newKey() +{ + int r=getEntropy(); + m_key=getRandom(40).toHex(); + if(r<(40*8))return r; + else return 40*8; +} + +bool MHost::create() +{ + //do not attempt to save invalid or incomplete data + if(!isValid())return false; + //create XML + QDomDocument doc; + QDomElement root=doc.createElement("Hosts"); + QDomElement el=doc.createElement("Host"); + el.setAttribute("name",m_hostid); + el.appendChild(doc.createTextNode(m_key)); + root.appendChild(el); + doc.appendChild(root); + //call + req->request("addhost",doc.toByteArray()); + //check success + if(req->responseStatus()==MWebRequest::Ok){ + //TODO: check response content for myself, return false if not found + return true; + }else{ + return false; + } +} + +bool MHost::save() +{ + //do not attempt to save invalid or incomplete data + if(!isValid())return false; + //create XML + QDomDocument doc; + QDomElement root=doc.createElement("Hosts"); + QDomElement el=doc.createElement("Host"); + el.setAttribute("name",m_hostid); + el.appendChild(doc.createTextNode(m_key)); + root.appendChild(el); + doc.appendChild(root); + //call + req->request("sethost",doc.toByteArray()); + //check success + if(req->responseStatus()==MWebRequest::Ok){ + //TODO: check response content for myself, return false if not found + return true; + }else{ + return false; + } +} + +void MHost::deleteHost() +{ + if(!isValid())return; + req->request("deletehost",m_hostid.toUtf8()); +} diff --git a/src/host.h b/src/host.h new file mode 100644 index 0000000..065acff --- /dev/null +++ b/src/host.h @@ -0,0 +1,59 @@ +// +// C++ Interface: host +// +// Description: +// +// +// Author: Konrad Rosenbaum , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#ifndef MAGICSMOKE_HOST_H +#define MAGICSMOKE_HOST_H + +#include + +class MWebRequest; +class QDomElement; + +class MHost +{ + public: + /**create invalid host*/ + MHost(); + /**create host by name*/ + MHost(MWebRequest*,QString,QString k=QString()); + /**create host from XML element*/ + MHost(MWebRequest*,QDomElement&); + /**copy host*/ + MHost(const MHost&); + + /**returns host name*/ + QString hostId(); + + /**returns host key (fetches it from DB if not known yet)*/ + QString hostKey(); + + /**checks host name*/ + bool isValid(); + + /**creates new host key for this host; returns number of entropy bits*/ + int newKey(); + + /**creates host in database; returns true on success*/ + bool create(); + + /**updates host key in database; returns true on success*/ + bool save(); + + /**deletes host from database*/ + void deleteHost(); + + private: + MWebRequest*req; + QString m_hostid,m_key; +}; + +#endif diff --git a/src/keygen.cpp b/src/keygen.cpp index dd8910d..a7fa561 100644 --- a/src/keygen.cpp +++ b/src/keygen.cpp @@ -224,3 +224,9 @@ QByteArray getRandom(int num) if(efilter.isNull())return QByteArray(); return efilter->getRandom(num); } + +int getEntropy() +{ + if(efilter.isNull())return 0; + return efilter->entropy(); +} diff --git a/src/keygen.h b/src/keygen.h index 1efc408..ea24539 100644 --- a/src/keygen.h +++ b/src/keygen.h @@ -61,5 +61,6 @@ class EFilter:public QObject //shortcut: QByteArray getRandom(int); +int getEntropy(); #endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 33455d4..444477d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -35,6 +35,7 @@ #include #include #include +#include MMainWindow::MMainWindow() { @@ -226,18 +227,30 @@ void MMainWindow::changeLang() void MMainWindow::exportKey() { - QString key=QSettings().value("hostkey").toString().trimmed(); - saveKey(key); + QSettings st; + QString host=st.value("hostname").toString().trimmed(); + QString key=st.value("hostkey").toString().trimmed(); + saveKey(host,key); } void MMainWindow::generateKey() { + QString name; + do{ + bool ok; + name=QInputDialog::getText(this,tr("New Host Name"),tr("Please enter a name for the new host:"),QLineEdit::Normal,name,&ok); + if(!ok)return; + if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(name)){ + QMessageBox::warning(this,tr("Warning"),tr("The host name must only consist of letters, digits and underscore. It must start with a letter.")); + continue; + } + }while(false); MKeyGen mkg; if(mkg.exec()==QDialog::Accepted) - saveKey(mkg.getKey()); + saveKey(name,mkg.getKey()); } -void MMainWindow::saveKey(QString key) +void MMainWindow::saveKey(QString host,QString key) { QStringList fn; QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)"); @@ -253,7 +266,7 @@ void MMainWindow::saveKey(QString key) return; } QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex(); - QString out="MagicSmokeHostKey\n"+key+"\n"+chk; + QString out="MagicSmokeHostKey\n"+host+"\n"+key+"\n"+chk; fd.write(out.toAscii()); fd.close(); } @@ -287,16 +300,22 @@ void MMainWindow::importKey() QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); return; } - QString key=fc[1].trimmed(); + QString hname=fc[1].trimmed(); + if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){ + QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name.")); + return; + } + QString key=fc[2].trimmed(); if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){ QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key.")); return; } QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex(); - if(chk!=fc[2].trimmed()){ + if(chk!=fc[3].trimmed()){ QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file.")); return; } //save QSettings().setValue("hostkey",key); + QSettings().setValue("hostname",hname); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 2d5b675..619fcc4 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -39,7 +39,7 @@ class MMainWindow:public QMainWindow QComboBox*profiles; //helper for exportKey and generateKey - void saveKey(QString); + void saveKey(QString hostname,QString hostkey); private slots: //handling of login/profile screen diff --git a/src/overview.cpp b/src/overview.cpp index 86f3018..1884745 100644 --- a/src/overview.cpp +++ b/src/overview.cpp @@ -29,6 +29,10 @@ #include #include #include +#include +#include +#include +#include MOverview::MOverview(MWebRequest*mw,QString pk) { @@ -147,6 +151,33 @@ MOverview::MOverview(MWebRequest*mw,QString pk) //host tab tab->addTab(hosttab=new QWidget,tr("Hosts")); + hosttab->setLayout(hl=new QHBoxLayout); + hl->addWidget(hosttable=new QTableView,10); + hosttable->setModel(hostmodel=new QStandardItemModel(this)); + hosttable->setSelectionMode(QAbstractItemView::SingleSelection); + hosttable->setEditTriggers(QAbstractItemView::NoEditTriggers); + hl->addSpacing(5); + hl->addLayout(vl=new QVBoxLayout,0); + vl->addWidget(p=new QPushButton(tr("New Host...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(newHost())); + p->setEnabled(req->hasRole("addhost")); + vl->addWidget(thishostbutton=p=new QPushButton(tr("Add This Host...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(addThisHost())); + p->setEnabled(req->hasRole("addhost")); + vl->addWidget(p=new QPushButton(tr("Delete Host...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(deleteHost())); + p->setEnabled(req->hasRole("deletehost")); + vl->addSpacing(20); + vl->addWidget(p=new QPushButton(tr("Generate New Key...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(changeHostKey())); + p->setEnabled(req->hasRole("sethostkey")); + vl->addWidget(p=new QPushButton(tr("Import...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(importHost())); + p->setEnabled(req->hasRole("addhost")); + vl->addWidget(p=new QPushButton(tr("Export...")),0); + connect(p,SIGNAL(clicked()),this,SLOT(exportHost())); + p->setEnabled(req->hasRole("gethostkey")); + vl->addStretch(10); //status bar statusBar()->setSizeGripEnabled(true); @@ -327,4 +358,166 @@ void MOverview::editUserHosts() } -void MOverview::updateHosts(){} +void MOverview::updateHosts() +{ + bool foundThis=false; + QString thisHost=req->hostName(); + QListhsl=req->getAllHosts(); + hostmodel->clear(); + hostmodel->insertColumns(0,2); + hostmodel->insertRows(0,hsl.size()); + hostmodel->setHorizontalHeaderLabels(QStringList()<setData(hostmodel->index(i,0),hsl[i].hostId()); + hostmodel->setData(hostmodel->index(i,1),hsl[i].hostKey()); + if(thisHost==hsl[i].hostId()) + foundThis=true; + } + hosttable->resizeColumnToContents(0); + hosttable->resizeColumnToContents(1); + thishostbutton->setEnabled(!foundThis && req->hasRole("addhost")); +} + +void MOverview::newHost() +{ + //get Host Name + QString hname; + do{ + bool ok; + hname=QInputDialog::getText(this,tr("Create New Host"),tr("Please enter a host name:"),QLineEdit::Normal,hname,&ok); + if(!ok)return; + if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname))continue; + }while(false); + //create it + MHost hst(req,hname); + int e=hst.newKey(); + if(e<128){ + if(QMessageBox::warning(this,tr("Warning"),tr("The key of this new host could only be generated with %1 bits entropy. Store anyway?").arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes) + return; + } + hst.create(); + //update + updateHosts(); +} + +void MOverview::addThisHost() +{ + MHost hst(req,req->hostName(),QSettings().value("hostkey").toString()); + hst.create(); + updateHosts(); +} + +void MOverview::deleteHost() +{ + //get selection + QModelIndex sel=hosttable->currentIndex(); + if(!sel.isValid())return; + //get hname + QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString(); + //ask + if(QMessageBox::question(this,tr("Delete this Host?"),tr("Really delete host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return; + //delete it + MHost(req,name).deleteHost(); + updateHosts(); +} + +void MOverview::changeHostKey() +{ + //get selection + QModelIndex sel=hosttable->currentIndex(); + if(!sel.isValid())return; + //get hname + QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString(); + //ask + if(QMessageBox::question(this,tr("Change Host Key?"),tr("Really change the key of host '%1'?").arg(name),QMessageBox::Yes|QMessageBox::No)!=QMessageBox::Yes)return; + //change it + MHost hst(req,name); + int e=hst.newKey(); + if(e<128){ + if(QMessageBox::warning(this,tr("Warning"),tr("The new key of this host could only be generated with %1 bits entropy. Store anyway?").arg(e),QMessageBox::Yes|QMessageBox::No,QMessageBox::No)!=QMessageBox::Yes) + return; + } + hst.save(); + //update + updateHosts(); +} + +void MOverview::importHost() +{ + QStringList fn; + QFileDialog fdlg(this,tr("Import Key from File"),QString(),"Magic Smoke Host Key (*.mshk)"); + fdlg.setDefaultSuffix("mshk"); + fdlg.setAcceptMode(QFileDialog::AcceptOpen); + fdlg.setFileMode(QFileDialog::ExistingFile); + if(!fdlg.exec())return; + fn=fdlg.selectedFiles(); + if(fn.size()!=1)return; + QFile fd(fn[0]); + if(!fd.open(QIODevice::ReadOnly)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for reading: %2").arg(fn[0]).arg(fd.errorString())); + return; + } + //read content (max: 10k to limit potential damage) + QStringList fc=QString::fromAscii(fd.read(10240)).split("\n",QString::SkipEmptyParts); + fd.close(); + //check content + if(fc.size()<3){ + QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); + return; + } + if(fc[0].trimmed()!="MagicSmokeHostKey"){ + QMessageBox::warning(this,tr("Warning"),tr("This is not a host key file.")); + return; + } + QString hname=fc[1].trimmed(); + if(!QRegExp("[A-Za-z][A-Za-z0-9_]*").exactMatch(hname)){ + QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid host name.")); + return; + } + QString key=fc[2].trimmed(); + if(!QRegExp("[0-9a-fA-F]+").exactMatch(key) || key.size()<40){ + QMessageBox::warning(this,tr("Warning"),tr("This host key file does not contain a valid key.")); + return; + } + QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex(); + if(chk!=fc[3].trimmed()){ + QMessageBox::warning(this,tr("Warning"),tr("The key check sum did not match. Please get a clean copy of the host key file.")); + return; + } + //save + MHost hst(req,hname,key); + hst.create(); + updateHosts(); +} + +void MOverview::exportHost() +{ + //get selection + QModelIndex sel=hosttable->currentIndex(); + if(!sel.isValid())return; + //get hname + QString name=hostmodel->data(hostmodel->index(sel.row(),0)).toString(); + QString key=hostmodel->data(hostmodel->index(sel.row(),1)).toString(); + if(name[0]=='_' || key==""){ + QMessageBox::warning(this,tr("Warning"),tr("This host cannot be exported.")); + return; + } + //save + QStringList fn; + QFileDialog fdlg(this,tr("Export Key to File"),QString(),"Magic Smoke Host Key (*.mshk)"); + fdlg.setDefaultSuffix("mshk"); + fdlg.setAcceptMode(QFileDialog::AcceptSave); + fdlg.setFileMode(QFileDialog::AnyFile); + if(!fdlg.exec())return; + fn=fdlg.selectedFiles(); + if(fn.size()!=1)return; + QFile fd(fn[0]); + if(!fd.open(QIODevice::WriteOnly|QIODevice::Truncate)){ + QMessageBox::warning(this,tr("Warning"),tr("Unable to open file %1 for writing: %2").arg(fn[0]).arg(fd.errorString())); + return; + } + QString chk=QCryptographicHash::hash(key.toAscii(),QCryptographicHash::Md5).toHex(); + QString out="MagicSmokeHostKey\n"+name+"\n"+key+"\n"+chk; + fd.write(out.toAscii()); + fd.close(); +} diff --git a/src/overview.h b/src/overview.h index dbd0f46..5f99fbc 100644 --- a/src/overview.h +++ b/src/overview.h @@ -20,6 +20,7 @@ class MWebRequest; class QTabWidget; class QTableView; class QStandardItemModel; +class QPushButton; /**Main Overview Window*/ class MOverview:public QMainWindow @@ -58,6 +59,19 @@ class MOverview:public QMainWindow /**update list of hosts*/ void updateHosts(); + /**create new host*/ + void newHost(); + /**create a database entry for this host*/ + void addThisHost(); + /**delete a host*/ + void deleteHost(); + /**generate a new key*/ + void changeHostKey(); + /**import host from file*/ + void importHost(); + /**export host to file*/ + void exportHost(); + private: //my session object QPointerreq; @@ -68,6 +82,7 @@ class MOverview:public QMainWindow QWidget*eventtab,*carttab,*usertab,*hosttab; QTableView*eventtable,*usertable,*hosttable; QStandardItemModel*eventmodel,*usermodel,*hostmodel; + QPushButton*thishostbutton; }; #endif diff --git a/src/smoke.pro b/src/smoke.pro index 0203a0f..c52c87b 100644 --- a/src/smoke.pro +++ b/src/smoke.pro @@ -33,6 +33,7 @@ SOURCES = \ event.cpp \ room.cpp \ user.cpp \ + host.cpp \ checkdlg.cpp HEADERS = \ keygen.h \ @@ -44,6 +45,7 @@ HEADERS = \ event.h \ room.h \ user.h \ + host.h \ checkdlg.h \ ../www/machine.php \ ../www/inc/machine/session.php diff --git a/src/webrequest.cpp b/src/webrequest.cpp index d9be3f4..b2e8b21 100644 --- a/src/webrequest.cpp +++ b/src/webrequest.cpp @@ -329,7 +329,7 @@ QList MWebRequest::getAllRooms() QDomDocument doc; QString msg;int ln,cl; if(!doc.setContent(rspdata,&msg,&ln,&cl)){ - errstr=tr("Error parsing EventList XML data (line %1 column %2): %3").arg(ln).arg(cl).arg(msg); + errstr=tr("Error parsing RoomList XML data (line %1 column %2): %3").arg(ln).arg(cl).arg(msg); return QList(); } QDomElement root=doc.documentElement(); @@ -352,7 +352,7 @@ QList MWebRequest::getAllUsers() QDomDocument doc; QString msg;int ln,cl; if(!doc.setContent(rspdata,&msg,&ln,&cl)){ - errstr=tr("Error parsing EventList XML data (line %1 column %2): %3").arg(ln).arg(cl).arg(msg); + errstr=tr("Error parsing UserList XML data (line %1 column %2): %3").arg(ln).arg(cl).arg(msg); return QList(); } QDomElement root=doc.documentElement(); @@ -367,6 +367,29 @@ QList MWebRequest::getAllUsers() return ret; } +QList MWebRequest::getAllHosts() +{ + errstr=""; + if(!request("gethosts",""))return QList(); + //parse return document + QDomDocument doc; + QString msg;int ln,cl; + if(!doc.setContent(rspdata,&msg,&ln,&cl)){ + errstr=tr("Error parsing HostList XML data (line %1 column %2): %3").arg(ln).arg(cl).arg(msg); + return QList(); + } + QDomElement root=doc.documentElement(); + QDomNodeList nl=root.elementsByTagName("Host"); + QListret; + for(int i=0;igetAllUsers(); + /**returns a list of all hosts**/ + QListgetAllHosts(); + + /**return current host name of this session*/ + QString hostName(); + public slots: /**set how long to wait for a web request*/ void setTimeout(int); diff --git a/www/inc/machine/host.php b/www/inc/machine/host.php new file mode 100644 index 0000000..dd1bde3 --- /dev/null +++ b/www/inc/machine/host.php @@ -0,0 +1,100 @@ +, (C) 2008 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +//return names&keys of all hosts +function getAllHostsXml() +{ + global $db; + header("X-MagicSmoke-Status: Ok"); + $res=$db->select("host","hostname,hostkey",""); + $dom=new DomDocument; + $root=$dom->createElement("Hosts"); + for($i=0;$icreateElement("Host",$res[$i]["hostkey"]); + $hst->setAttributeNode(new DOMAttr("name",$res[$i]["hostname"])); + $root->appendChild($hst); + } + $dom->appendChild($root); + print($dom->saveXML()); +} + +//create a new host +function addHostXml($txt) +{ + global $db; + $hlist=parseHostXml($txt); + foreach($hlist as $host){ + //check name + if(ereg("^[A-Za-z][A-Za-z0-9_]*$",$host["name"])===false)continue; + //create + $db->insert("host",array("hostname"=>$host["name"],"hostkey"=>$host["key"])); + } + header("X-MagicSmoke-Status: Ok"); + //FIXME: return a useful answer +} + +//change a host +function setHostXml($txt) +{ + global $db; + $hlist=parseHostXml($txt); + foreach($hlist as $host){ + //check name + if(ereg("^[A-Za-z][A-Za-z0-9_]*$",$host["name"])===false)continue; + //update + $db->update("host",array("hostkey"=>$host["key"]),"hostname=".$db->escapeString($host["name"])); + } + header("X-MagicSmoke-Status: Ok"); + //FIXME: return a useful answer +} + +//helper: parse host data +function parseHostXml($txt) +{ + $xml=new DOMDocument; + if(!$xml->loadXML($txt)){ + header("X-MagicSmoke-Status: SyntaxError"); + die("unable to parse XML data"); + } + $ret=array(); + foreach($xml->getElementsByTagName("Host") as $el){ + $usr["name"]=$el->getAttribute("name"); + $usr["key"]=""; + foreach($el->childNodes as $cn) + if($cn->nodeType==XML_TEXT_NODE) + $usr["key"]=$cn->wholeText; + $ret[]=$usr; + } + return $ret; +} + +//delete a host +function deleteHostXml($txt) +{ + global $db; + $hst=trim($txt); + //check syntax + if(substr($hst,0,1)=="_"){ + header("X-MagicSmoke-Status: Error"); + die("Cannot delete special hosts."); + } + //delete Host from users + $db->deleteRows("userhosts","host=".$db->escapeString($hst)); + //delete Host + $db->deleteRows("host","hostname=".$db->escapeString($hst)); + //say OK anyway; FIXME: check for success above + header("X-MagicSmoke-Status: Ok"); +} + + +?> \ No newline at end of file diff --git a/www/machine.php b/www/machine.php index 9f92709..835e419 100644 --- a/www/machine.php +++ b/www/machine.php @@ -51,6 +51,7 @@ include("inc/loader_nonadmin.php"); //load machine interface include("inc/machine/session.php"); +include("inc/machine/host.php"); // request to start a session if($SMOKEREQUEST=="startsession"){ @@ -157,33 +158,52 @@ if($SMOKEREQUEST=="getuseracl"){ getUserAclXml($REQUESTDATA); exit(); } - +//set the ACL of a specific user if($SMOKEREQUEST=="setuseracl"){ setUserAclXml($REQUESTDATA); exit(); } +//get the allowed client hosts of a specific user if($SMOKEREQUEST=="getuserhosts"){ getUserHostsXml($REQUESTDATA); exit(); } +//set the allowed client hosts of a specific user if($SMOKEREQUEST=="setuserhosts"){ setUserHostsXml($REQUESTDATA); exit(); } - +//create a new user if($SMOKEREQUEST=="adduser"){ addUserXml($REQUESTDATA); exit(); } - +//delete an user if($SMOKEREQUEST=="deleteuser"){ deleteUserXml($REQUESTDATA); exit(); } -if($SMOKEREQUEST=="gethosts"){} -if($SMOKEREQUEST=="sethost"){} -if($SMOKEREQUEST=="addhost"){} -if($SMOKEREQUEST=="deletehost"){} + +//return a list of all hosts with their keys +// there is currently no transaction to get names only, since this is +// implied in getuserhosts +if($SMOKEREQUEST=="gethosts"){ + getAllHostsXml(); + exit(); +} +//change the key of a host +if($SMOKEREQUEST=="sethost"){ + setHostXml($REQUESTDATA); +} +//create a new host entry +if($SMOKEREQUEST=="addhost"){ + addHostXml($REQUESTDATA); + exit(); +} +if($SMOKEREQUEST=="deletehost"){ + deleteHostXml($REQUESTDATA); + exit(); +} //EOF -- 1.7.2.5