Walnut/Persistent Secure Distributed Computing

From Erights

(Difference between revisions)
Jump to: navigation, search
(Persistent Secure Distributed Computing: changed case of an internal link)
(Example: Persistent eChat: put in the code from echat.e-awt)
Line 10: Line 10:
===Example: Persistent eChat===
===Example: Persistent eChat===
 +
 +
<code filename="echat.e-awt"><pre>
 +
#!/usr/bin/env rune
 +
 +
pragma.syntax("0.8")
 +
 +
# Copyright 2002 Combex, Inc. under the terms of the MIT X license
 +
# found at http://www.opensource.org/licenses/mit-license.html ................
 +
 +
/**
 +
* set up tracing; stub out all the printing for operational version
 +
*/
 +
def traceline(str) :void {
 +
    stderr.println(str)
 +
}
 +
 +
# Ensure the user knows if he's using a clear, unencrypted connection
 +
traceline(introducer.negotiable())
 +
 +
#def Title := if (introducer negotiable() == ["3DES_SDH_M"]) {
 +
#    "Secure EChat"
 +
#} else {
 +
#    <swing:makeJOptionPane> showMessageDialog(
 +
#        null,
 +
#        "You are using DaffE, so you'll be chatting in the clear.
 +
#To be secure, use E instead.",
 +
#        "Unencrypted DaffE Session",
 +
#        <swing:makeJOptionPane> WARNING_MESSAGE())
 +
#    "EChat"
 +
#}
 +
def Title := "eChat"
 +
 +
def chatReceiver
 +
def sturdyChatReceiver
 +
 +
if (interp.getArgs() =~ [`-save`, filename]) {
 +
    throw("use persist-echat.e-awt")
 +
} else if (interp.getArgs() =~ [`-restore`, filename]) {
 +
    throw("use persist-echat.e-awt")
 +
} else {
 +
    traceline("once only incarnation")
 +
    introducer.onTheAir()
 +
    def [bind sturdyChatReceiver, _, _] :=
 +
      identityMgr.makeKnown(chatReceiver)
 +
}
 +
traceline(introducer)
 +
traceline(sturdyChatReceiver)
 +
 +
/**
 +
* return the object represented by the URI
 +
*/
 +
def getObjectFromURI(uri) :any {
 +
    introducer.sturdyFromURI(uri).getRcvr()
 +
}
 +
 +
/**
 +
* return the friend file
 +
*/
 +
def findFriendFile(chatWin) :any {
 +
    def dialog := <awt:makeFileDialog>(chatWin, "Select a Friend")
 +
    dialog.show()
 +
    var path := dialog.getFile()
 +
    if (path != null) {
 +
        path := dialog.getDirectory() + path
 +
    }
 +
    <file>[path]
 +
}
 +
 +
/**
 +
* return a file to be saved
 +
*/
 +
def requestSaveFile(chatWin) :any {
 +
    def dialog := <awt:makeFileDialog>(chatWin,
 +
                                  "Save File with Your Name",
 +
                                  <awt:makeFileDialog>.getSAVE())
 +
    dialog.show()
 +
    var addressName := dialog.getFile()
 +
    if (addressName != null) {
 +
        addressName := dialog.getDirectory() + addressName
 +
    }
 +
    <file>[addressName]
 +
}
 +
 +
/**
 +
* method that writes out the URI for your echat system's communication
 +
* interface
 +
*/
 +
def offerMyAddress(file, uri) :void {
 +
    traceline(`$file setText("$uri")`)
 +
    file.setText(uri)
 +
}
 +
 +
def set1LineComponentParameters(component) :void {
 +
    component.setPreferredSize(<awt:makeDimension>(150,25))
 +
    component.setMaximumSize(<awt:makeDimension>(1000,25))
 +
    component.setAlignmentX(0.5)
 +
}
 +
 +
def chatUIMaker(chatController) :any {
 +
    # Lay out the chat window, create its components
 +
    def chatWin := <swing:makeJFrame>(Title)
 +
    def chatPane := chatWin.getContentPane()
 +
    def border := <swing:makeBoxLayout>(chatPane,1)
 +
    chatPane.setLayout(border)
 +
    traceline("p1 ui made");
 +
    def windowListener {
 +
        to windowClosing(event) :void {
 +
            chatController.leave()
 +
            traceline("trying to exit")
 +
            interp.continueAtTop()
 +
        }
 +
        match _ {}
 +
    }
 +
    chatWin.addWindowListener(windowListener)
 +
    traceline("p2 ui made");
 +
 +
    /**
 +
    * make a button that calls the chatController
 +
    */
 +
    def newButton(labelText, verb) :any {
 +
        # def button := <swing:makeJButton>(labelText)
 +
        def button := <swing:makeJButton>(labelText)
 +
        traceline("made button")
 +
        set1LineComponentParameters(button)
 +
        def buttonListener {
 +
            to actionPerformed(event) :void {
 +
                E.call(chatController, verb, [])
 +
            }
 +
        }
 +
        button.addActionListener(buttonListener)
 +
        traceline("button being returned")
 +
        button
 +
    }
 +
 +
    # setNameButton
 +
    def setNameButton := newButton("Set Your Name", "setMyName")
 +
 +
    # offerChatButton
 +
    def offerChatButton := newButton("Offer Chat", "offerSelf")
 +
    offerChatButton.setEnabled(false)
 +
 +
    # findFriendButton
 +
    def findFriendButton := newButton("Find Friend", "findFriend")
 +
    findFriendButton.setEnabled(false)
 +
 +
    # chatScroller that holds chatTextArea
 +
    def chatScroller := <swing:makeJScrollPane>()
 +
    chatScroller.setMaximumSize(<awt:makeDimension>(2000,1000))
 +
    chatScroller.setPreferredSize(<awt:makeDimension>(250,80))
 +
 +
    # chatTextArea
 +
    def chatTextArea := <swing:makeJTextArea>()
 +
    chatTextArea.setLineWrap(true)
 +
    chatScroller.getViewport().add(chatTextArea)
 +
 +
    # nextMessageBox
 +
    def nextMessageBox := <swing:makeJTextField>("Type your message here",30)
 +
    set1LineComponentParameters(nextMessageBox)
 +
    chatPane.add(nextMessageBox)
 +
    traceline("p3 ui buildt");
 +
 +
    # sendMessageButton
 +
    def sendMessageButton := newButton("Send", "send")
 +
    sendMessageButton.setEnabled(false)
 +
 +
    chatPane.add(JPanel`$setNameButton
 +
                        $offerChatButton $findFriendButton
 +
                        $chatScroller.Y
 +
                        $nextMessageBox
 +
                        $sendMessageButton`)
 +
 +
    chatWin.pack()
 +
    chatWin.show()
 +
 +
    def chatUI {
 +
        to getChatWin()          :any { chatWin }
 +
        to getNameButton()        :any { setNameButton }
 +
        to getOfferChatButton()  :any { offerChatButton }
 +
        to getFindFriendButton()  :any { findFriendButton }
 +
        to getChatTextArea()      :any { chatTextArea }
 +
        to getNextMessageBox()    :any { nextMessageBox }
 +
        to getSendMessageButton() :any { sendMessageButton }
 +
    }
 +
}
 +
 +
/**
 +
* facet of chatController sent to other chatter with only appropriate
 +
* messages
 +
*/
 +
def chatReceiverMaker(var chatController) :any {
 +
    bind chatReceiver {
 +
        to receive(message) :void { chatController.receive(message) }
 +
        to receiveFriend(friend, name) :any {
 +
            chatController.receiveFriend(friend, name)
 +
        }
 +
        to friendIsLeaving() :void { chatController.friendIsLeaving() }
 +
        to revoke() :void { chatController := null }
 +
    }
 +
}
 +
 +
/**
 +
* @author Marc Stiegler
 +
*/
 +
def chatControllerMaker() :any {
 +
    def chatController := {
 +
        def chatUI := chatUIMaker(chatController)
 +
        def myChatReceiver := chatReceiverMaker(chatController)
 +
        var myName := null
 +
        var myFriend := null
 +
        var myFriendName := null
 +
        var myAddressFile := null
 +
        traceline("initialized chatController");
 +
        def showMessage(senderName, message) :void {
 +
            chatUI.getChatTextArea().append(
 +
                senderName +" says:\t"+ message + "\n")
 +
        }
 +
        def showDebug(message) :void {
 +
            # chatUI getChatTextArea() append("Debug: " + message + "\n")
 +
        }
 +
        def chatController {
 +
 +
            /**
 +
            * transmitting functions
 +
            */
 +
            to send() :void {
 +
                def nextMsgBox := chatUI.getNextMessageBox()
 +
                def nextMessage := nextMsgBox.getText()
 +
                nextMsgBox.setText("")
 +
                traceline("next message" + nextMessage)
 +
                myFriend <- receive(nextMessage)
 +
                showMessage(myName, nextMessage)
 +
            }
 +
            to setMyName() :void {
 +
                myName := <swing:makeJOptionPane>.showInputDialog(
 +
                    "Please give me your name for this chat session")
 +
                traceline(`name: $myName`)
 +
                if (myName != null) {
 +
                    chatUI.getNameButton().setLabel(myName)
 +
                    chatUI.getNameButton().setEnabled(false)
 +
                    chatUI.getOfferChatButton().setEnabled(true)
 +
                    chatUI.getFindFriendButton().setEnabled(true)
 +
                }
 +
            }
 +
            to offerSelf() :void {
 +
                myAddressFile := requestSaveFile(chatUI.getChatWin())
 +
                if (myAddressFile != null) {
 +
                    def uri := introducer.sturdyToURI(sturdyChatReceiver)
 +
                    offerMyAddress(myAddressFile, uri)
 +
                }
 +
            }
 +
            to leave() :void {
 +
                if (myAddressFile != null) {
 +
                    # myAddressFile delete(null)
 +
                }
 +
                myFriend <- friendIsLeaving()
 +
                chatController.disconnect("is being left")
 +
            }
 +
            to receive(message) :void {
 +
                showMessage(myFriendName, message)
 +
            }
 +
            to receiveFriend(friend, name) :any {
 +
                traceline("receiveFriend")
 +
                myFriend := friend
 +
                myFriendName := name
 +
                chatUI.getSendMessageButton().setEnabled(true)
 +
                chatUI.getOfferChatButton().setEnabled(false)
 +
                chatUI.getFindFriendButton().setEnabled(false)
 +
                chatUI.getChatTextArea().append(
 +
                    myFriendName + " has arrived\n")
 +
                Ref.whenBroken(friend, def observer(prom) :void {
 +
                    chatController.disconnect("disconnected")
 +
                })
 +
                traceline("received")
 +
                myName
 +
            }
 +
            to findFriend() :void {
 +
                def file := findFriendFile(chatUI.getChatWin())
 +
                if (file != null) {
 +
                    def friendURI := file.getText()
 +
                    showDebug("uri " + friendURI)
 +
                    def friend := getObjectFromURI(friendURI)
 +
                    showDebug("obj " + friend)
 +
 +
                    when (friend <- receiveFriend(myChatReceiver, myName)) ->
 +
                      done(friendName) :void {
 +
 +
                        showDebug("won against all odds")
 +
                        chatController.receiveFriend(friend, friendName)
 +
                    } catch problem {
 +
                        showDebug("clobbered: " + problem)
 +
                        chatController.disconnect("is unreachable")
 +
                    }
 +
 +
                    showDebug("sent me")
 +
                }
 +
            }
 +
            to friendIsLeaving() :void {
 +
                chatController.disconnect("is leaving")
 +
            }
 +
            to disconnect(desc) :void {
 +
                chatUI.getSendMessageButton().setEnabled(false)
 +
                if (myFriendName == null) {
 +
                    myFriendName := "the friend"
 +
                }
 +
                chatUI.getChatTextArea().append(
 +
                    myFriendName + " " + desc + "\n")
 +
                myFriend := null
 +
                myFriendName := null
 +
                myChatReceiver.revoke()
 +
            }
 +
        }
 +
    }
 +
}
 +
 +
def controller := chatControllerMaker()
 +
traceline(interp.getArgs())
 +
interp.blockAtTop()
 +
 +
 +
</pre></code>
 +
 +
Next Section: [[Walnut/Secure_Mobile_Code|Secure Mobile Code]]
Next Section: [[Walnut/Secure_Mobile_Code|Secure Mobile Code]]

Revision as of 04:03, 5 March 2008


Persistent Secure Distributed Computing

There is a problem with the programs we explored in the last chapter. The MarketPlace server, the RaceTrack server, and eChat are not persistent: once you shut them down they are gone forever. You can start up a new server with the same code, but it will not return to life with the same URI it had before. As a consequence, if you restart a server, you must redistribute the capability to access that server to all the users. This is a logistical nightmare. When we restart one of these servers, it must be able to restart with the same VatID and object IDs it had before.

If E simply allowed objects to remember their own URIs, there would be extensive opportunities for object forgery in the mobile code systems described in the next chapter. To prevent such forgeries, E uses swiss bases for persistence.

Swiss Bases

Example: Persistent eChat

#!/usr/bin/env rune

pragma.syntax("0.8")

# Copyright 2002 Combex, Inc. under the terms of the MIT X license
# found at http://www.opensource.org/licenses/mit-license.html ................

/**
 * set up tracing; stub out all the printing for operational version
 */
def traceline(str) :void {
    stderr.println(str)
}

# Ensure the user knows if he's using a clear, unencrypted connection
traceline(introducer.negotiable())

#def Title := if (introducer negotiable() == ["3DES_SDH_M"]) {
#    "Secure EChat"
#} else {
#    <swing:makeJOptionPane> showMessageDialog(
#        null,
#        "You are using DaffE, so you'll be chatting in the clear.
#To be secure, use E instead.",
#        "Unencrypted DaffE Session",
#        <swing:makeJOptionPane> WARNING_MESSAGE())
#    "EChat"
#}
def Title := "eChat"

def chatReceiver
def sturdyChatReceiver

if (interp.getArgs() =~ [`-save`, filename]) {
    throw("use persist-echat.e-awt")
} else if (interp.getArgs() =~ [`-restore`, filename]) {
    throw("use persist-echat.e-awt")
} else {
    traceline("once only incarnation")
    introducer.onTheAir()
    def [bind sturdyChatReceiver, _, _] :=
      identityMgr.makeKnown(chatReceiver)
}
traceline(introducer)
traceline(sturdyChatReceiver)

/**
 * return the object represented by the URI
 */
def getObjectFromURI(uri) :any {
    introducer.sturdyFromURI(uri).getRcvr()
}

/**
 * return the friend file
 */
def findFriendFile(chatWin) :any {
    def dialog := <awt:makeFileDialog>(chatWin, "Select a Friend")
    dialog.show()
    var path := dialog.getFile()
    if (path != null) {
        path := dialog.getDirectory() + path
    }
    <file>[path]
}

/**
 * return a file to be saved
 */
def requestSaveFile(chatWin) :any {
    def dialog := <awt:makeFileDialog>(chatWin,
                                   "Save File with Your Name",
                                   <awt:makeFileDialog>.getSAVE())
    dialog.show()
    var addressName := dialog.getFile()
    if (addressName != null) {
        addressName := dialog.getDirectory() + addressName
    }
    <file>[addressName]
}

/**
 * method that writes out the URI for your echat system's communication
 * interface
 */
def offerMyAddress(file, uri) :void {
    traceline(`$file setText("$uri")`)
    file.setText(uri)
}

def set1LineComponentParameters(component) :void {
    component.setPreferredSize(<awt:makeDimension>(150,25))
    component.setMaximumSize(<awt:makeDimension>(1000,25))
    component.setAlignmentX(0.5)
}

def chatUIMaker(chatController) :any {
    # Lay out the chat window, create its components
    def chatWin := <swing:makeJFrame>(Title)
    def chatPane := chatWin.getContentPane()
    def border := <swing:makeBoxLayout>(chatPane,1)
    chatPane.setLayout(border)
    traceline("p1 ui made");
    def windowListener {
        to windowClosing(event) :void {
            chatController.leave()
            traceline("trying to exit")
            interp.continueAtTop()
        }
        match _ {}
    }
    chatWin.addWindowListener(windowListener)
    traceline("p2 ui made");

    /**
     * make a button that calls the chatController
     */
    def newButton(labelText, verb) :any {
        # def button := <swing:makeJButton>(labelText)
        def button := <swing:makeJButton>(labelText)
        traceline("made button")
        set1LineComponentParameters(button)
        def buttonListener {
            to actionPerformed(event) :void {
                E.call(chatController, verb, [])
            }
        }
        button.addActionListener(buttonListener)
        traceline("button being returned")
        button
    }

    # setNameButton
    def setNameButton := newButton("Set Your Name", "setMyName")

    # offerChatButton
    def offerChatButton := newButton("Offer Chat", "offerSelf")
    offerChatButton.setEnabled(false)

    # findFriendButton
    def findFriendButton := newButton("Find Friend", "findFriend")
    findFriendButton.setEnabled(false)

    # chatScroller that holds chatTextArea
    def chatScroller := <swing:makeJScrollPane>()
    chatScroller.setMaximumSize(<awt:makeDimension>(2000,1000))
    chatScroller.setPreferredSize(<awt:makeDimension>(250,80))

    # chatTextArea
    def chatTextArea := <swing:makeJTextArea>()
    chatTextArea.setLineWrap(true)
    chatScroller.getViewport().add(chatTextArea)

    # nextMessageBox
    def nextMessageBox := <swing:makeJTextField>("Type your message here",30)
    set1LineComponentParameters(nextMessageBox)
    chatPane.add(nextMessageBox)
    traceline("p3 ui buildt");

    # sendMessageButton
    def sendMessageButton := newButton("Send", "send")
    sendMessageButton.setEnabled(false)

    chatPane.add(JPanel`$setNameButton
                        $offerChatButton $findFriendButton
                        $chatScroller.Y
                        $nextMessageBox
                        $sendMessageButton`)

    chatWin.pack()
    chatWin.show()

    def chatUI {
        to getChatWin()           :any { chatWin }
        to getNameButton()        :any { setNameButton }
        to getOfferChatButton()   :any { offerChatButton }
        to getFindFriendButton()  :any { findFriendButton }
        to getChatTextArea()      :any { chatTextArea }
        to getNextMessageBox()    :any { nextMessageBox }
        to getSendMessageButton() :any { sendMessageButton }
    }
}

/**
 * facet of chatController sent to other chatter with only appropriate
 * messages
 */
def chatReceiverMaker(var chatController) :any {
    bind chatReceiver {
        to receive(message) :void { chatController.receive(message) }
        to receiveFriend(friend, name) :any {
            chatController.receiveFriend(friend, name)
        }
        to friendIsLeaving() :void { chatController.friendIsLeaving() }
        to revoke() :void { chatController := null }
    }
}

/**
 * @author Marc Stiegler
 */
def chatControllerMaker() :any {
    def chatController := {
        def chatUI := chatUIMaker(chatController)
        def myChatReceiver := chatReceiverMaker(chatController)
        var myName := null
        var myFriend := null
        var myFriendName := null
        var myAddressFile := null
        traceline("initialized chatController");
        def showMessage(senderName, message) :void {
            chatUI.getChatTextArea().append(
                senderName +" says:\t"+ message + "\n")
        }
        def showDebug(message) :void {
            # chatUI getChatTextArea() append("Debug: " + message + "\n")
        }
        def chatController {

            /**
             * transmitting functions
             */
            to send() :void {
                def nextMsgBox := chatUI.getNextMessageBox()
                def nextMessage := nextMsgBox.getText()
                nextMsgBox.setText("")
                traceline("next message" + nextMessage)
                myFriend <- receive(nextMessage)
                showMessage(myName, nextMessage)
            }
            to setMyName() :void {
                myName := <swing:makeJOptionPane>.showInputDialog(
                    "Please give me your name for this chat session")
                traceline(`name: $myName`)
                if (myName != null) {
                    chatUI.getNameButton().setLabel(myName)
                    chatUI.getNameButton().setEnabled(false)
                    chatUI.getOfferChatButton().setEnabled(true)
                    chatUI.getFindFriendButton().setEnabled(true)
                }
            }
            to offerSelf() :void {
                myAddressFile := requestSaveFile(chatUI.getChatWin())
                if (myAddressFile != null) {
                    def uri := introducer.sturdyToURI(sturdyChatReceiver)
                    offerMyAddress(myAddressFile, uri)
                }
            }
            to leave() :void {
                if (myAddressFile != null) {
                    # myAddressFile delete(null)
                }
                myFriend <- friendIsLeaving()
                chatController.disconnect("is being left")
            }
            to receive(message) :void {
                showMessage(myFriendName, message)
            }
            to receiveFriend(friend, name) :any {
                traceline("receiveFriend")
                myFriend := friend
                myFriendName := name
                chatUI.getSendMessageButton().setEnabled(true)
                chatUI.getOfferChatButton().setEnabled(false)
                chatUI.getFindFriendButton().setEnabled(false)
                chatUI.getChatTextArea().append(
                    myFriendName + " has arrived\n")
                Ref.whenBroken(friend, def observer(prom) :void {
                    chatController.disconnect("disconnected")
                })
                traceline("received")
                myName
            }
            to findFriend() :void {
                def file := findFriendFile(chatUI.getChatWin())
                if (file != null) {
                    def friendURI := file.getText()
                    showDebug("uri " + friendURI)
                    def friend := getObjectFromURI(friendURI)
                    showDebug("obj " + friend)

                    when (friend <- receiveFriend(myChatReceiver, myName)) ->
                      done(friendName) :void {

                        showDebug("won against all odds")
                        chatController.receiveFriend(friend, friendName)
                    } catch problem {
                        showDebug("clobbered: " + problem)
                        chatController.disconnect("is unreachable")
                    }

                    showDebug("sent me")
                }
            }
            to friendIsLeaving() :void {
                chatController.disconnect("is leaving")
            }
            to disconnect(desc) :void {
                chatUI.getSendMessageButton().setEnabled(false)
                if (myFriendName == null) {
                    myFriendName := "the friend"
                }
                chatUI.getChatTextArea().append(
                    myFriendName + " " + desc + "\n")
                myFriend := null
                myFriendName := null
                myChatReceiver.revoke()
            }
        }
    }
}

def controller := chatControllerMaker()
traceline(interp.getArgs())
interp.blockAtTop()



Next Section: Secure Mobile Code

Personal tools
more tools