From: D Yuniskis on
Hi,

I'm looking for ideas for a lightweight (yet robust)
autoupdate protocol for a family of network clients
I'm designing.

Some criteria:

- Unattended, persistent operation. A device shouldn't
require hand-holding from a user to get itself into a
working configuration. It is acceptable (though not
*desireable*) to withold its normal functionality
from the user while updating *or* recovering from a
botched upgrade. But, it must be able to eventually
"right itself".

- I don't want to have to *tell* the devices that they
need to be updated. The user shouldn't even be aware
that this is happening. I.e., the devices should be
able to examine/query the "current images" to see if
they coincide with *their* images.

- I should be able to tailor an image to a *particular*
device (i.e., an *instance* of a device; not just a
"model number").

- Images need to be signed so they can't be forged.

- The protocol can't be spoofed by "unfriendlies".

- The protocol should be as light as possible -- but
no lighter! ;-)

- Minimize unnecessary network traffic as well as
load on the server (the goal is for the user *not*
to notice this activity -- though I am not trying
to "keep it secret")

(seems like I have forgotten something -- but I
can't recall what! :< Too early in the day...)

So, all I should have to do is put "current images"
on the user's server and wait for each device to
discover the image and update itself accordingly.

For example, the devices could check the server at IPL
(and periodically at run time -- though updates at
run time can be more of a challenge as they will
probably interfere with normal operation :< )
and "fingerprint" the current image located there
to see if it looks like it differs from its own
image.

One way of doing this is to store the image for
each device instance in a R/O file bearing the MAC
of the device in question. But, this would
require the device to perform a "trial download"
of the image for the sole purpose of computing
the fingerprint (why not just do a bytewise compare
if you are going to this extreme?!).

This will hammer the network pretty hard. Granted,
the individual segments for each device will see
modest traffic -- but the server's segment will
quickly max out if multiple devices do this
simultaneously (e.g., powering up together).
This would necessitate a second layer of the
protocol to randomize/defer such competition. :<

Another approach is to *store* the fingerprint on the
server in a uniquely accessible manner (e.g., use
a file name like MAC.fingerprint). But, that represents
a duplication of data (pet peeve of mine) which makes
it at risk for getting out of sync.

For example, updating the image and forgetting to update
the fingerprint; or, a run-time race -- the device
examines the fingerprint, sees that it differs, starts
to download image but the image hasn't been updated
yet. Or, the image is updated but the fingerprint
is stale when the device examines it. As a result,
the image is NOT seen as "new".

[you could get around this if you implemented network
file locking -- but that is more complexity and leaves
open the possibility of stale locks, etc.]

This could be worked around by forcing the server to
recompute the fingerprint each time an image is added.
But, that still leaves a race window *and* requires
the server to be aware of the introduction of the
new image file(s).

The simplest compromise would seem to be having the
device track the timestamp of the image file and
check *that*. If changed, then *assume* the image
actually has changed (of course, touch(1)-ing the
image file would then force the device to consider
the image file as changed -- this could be an
advantage?). The device could then either
fingerprint the image itself *or* naively assume
it to be a new image and begin the (secure) update
procedure.

Security then is another facet to be addressed. E.g.,
given that the devices *don't* have enough resources to
store an entire image before flashing, the protocol
would have to be interruptible. E.g., encrypted
packets so they can't be spoofed. But, accepting
the possibility that the entire image might not
become available "when needed" for the reflash.
I.e., fall back to a secure boot loader that
can do the update without the rest of the application
being available.

Note that this loader should *not* restart the upload
but, instead, *continue* where it apparently left off,
previously -- even in light of any intervening power
cycles. This saves time, reduces flash wear and is
just "smarter", in general. :>

But, it seems like this *still* requires server side
locking so the file isn't changed *while* it is being
doled out. E.g., something like TFTP would be
inappropriate as it doesn't reliably lock the file
from one packet to the next.

Shirley, this sort of thing has been done before (?).
Pointers?

Thanks!
--don
From: Ignacio G. T. on
El 08/03/2010 20:34, D Yuniskis escribi�:
> Hi,
>
> I'm looking for ideas for a lightweight (yet robust)
> autoupdate protocol for a family of network clients
> I'm designing.

[...]

> Another approach is to *store* the fingerprint on the
> server in a uniquely accessible manner (e.g., use
> a file name like MAC.fingerprint). But, that represents
> a duplication of data (pet peeve of mine) which makes
> it at risk for getting out of sync.

You could embed the fingerprint inside the image, at a reserved space in
its beginning.
--
Saludos.
Ignacio G.T.

From: Boudewijn Dijkstra on
Op Mon, 08 Mar 2010 20:34:53 +0100 schreef D Yuniskis
<not.going.to.be(a)seen.com>:
> I'm looking for ideas for a lightweight (yet robust)
> autoupdate protocol for a family of network clients
> I'm designing.
>
> Some criteria:
>
> - Unattended, persistent operation. A device shouldn't
> require hand-holding from a user to get itself into a
> working configuration. It is acceptable (though not
> *desireable*) to withold its normal functionality
> from the user while updating *or* recovering from a
> botched upgrade. But, it must be able to eventually
> "right itself".
>
> - I don't want to have to *tell* the devices that they
> need to be updated. The user shouldn't even be aware
> that this is happening. I.e., the devices should be
> able to examine/query the "current images" to see if
> they coincide with *their* images.
>
> - I should be able to tailor an image to a *particular*
> device (i.e., an *instance* of a device; not just a
> "model number").
>
> - Images need to be signed so they can't be forged.
>
> - The protocol can't be spoofed by "unfriendlies".
>
> - The protocol should be as light as possible -- but
> no lighter! ;-)
>
> - Minimize unnecessary network traffic as well as
> load on the server (the goal is for the user *not*
> to notice this activity -- though I am not trying
> to "keep it secret")
>
> (seems like I have forgotten something -- but I
> can't recall what! :< Too early in the day...)
>
> So, all I should have to do is put "current images"
> on the user's server and wait for each device to
> discover the image and update itself accordingly.
>
> For example, the devices could check the server at IPL
> (and periodically at run time -- though updates at
> run time can be more of a challenge as they will
> probably interfere with normal operation :< )
> and "fingerprint" the current image located there
> to see if it looks like it differs from its own
> image.
>
> One way of doing this is to store the image for
> each device instance in a R/O file bearing the MAC
> of the device in question. But, this would
> require the device to perform a "trial download"
> of the image for the sole purpose of computing
> the fingerprint (why not just do a bytewise compare
> if you are going to this extreme?!).
>
> This will hammer the network pretty hard. Granted,
> the individual segments for each device will see
> modest traffic -- but the server's segment will
> quickly max out if multiple devices do this
> simultaneously (e.g., powering up together).
> This would necessitate a second layer of the
> protocol to randomize/defer such competition. :<
>
> Another approach is to *store* the fingerprint on the
> server in a uniquely accessible manner (e.g., use
> a file name like MAC.fingerprint). But, that represents
> a duplication of data (pet peeve of mine) which makes
> it at risk for getting out of sync.
>
> For example, updating the image and forgetting to update
> the fingerprint;

That's a bug.

> or, a run-time race -- the device
> examines the fingerprint, sees that it differs, starts
> to download image but the image hasn't been updated
> yet.

How can the server know the fingerprint before it has been fully updated?

> Or, the image is updated but the fingerprint
> is stale when the device examines it. As a result,
> the image is NOT seen as "new".

No biggy. The device will check again sometime, right?

> [you could get around this if you implemented network
> file locking -- but that is more complexity and leaves
> open the possibility of stale locks, etc.]

Have you considered your own simple protocol? E.g.
* client identifies to server and asks for update since $TIMESTAMP
* server says yes or no
* if yes, start streaming

> This could be worked around by forcing the server to
> recompute the fingerprint each time an image is added.
> But, that still leaves a race window

Only if the image is already accessible while the fingerprint isn't there
yet. And why would you do that?

> *and* requires
> the server to be aware of the introduction of the
> new image file(s).
>
> The simplest compromise would seem to be having the
> device track the timestamp of the image file and
> check *that*. If changed, then *assume* the image
> actually has changed (of course, touch(1)-ing the
> image file would then force the device to consider
> the image file as changed -- this could be an
> advantage?). The device could then either
> fingerprint the image itself *or* naively assume
> it to be a new image and begin the (secure) update
> procedure.
>
> Security then is another facet to be addressed. E.g.,
> given that the devices *don't* have enough resources to
> store an entire image before flashing, the protocol
> would have to be interruptible. E.g., encrypted
> packets so they can't be spoofed. But, accepting
> the possibility that the entire image might not
> become available "when needed" for the reflash.
> I.e., fall back to a secure boot loader that
> can do the update without the rest of the application
> being available.
>
> Note that this loader should *not* restart the upload
> but, instead, *continue* where it apparently left off,
> previously -- even in light of any intervening power
> cycles. This saves time, reduces flash wear and is
> just "smarter", in general. :>
>
> But, it seems like this *still* requires server side
> locking so the file isn't changed *while* it is being
> doled out.

Why would you do that? Each unique image should have a unique name.

> E.g., something like TFTP would be
> inappropriate as it doesn't reliably lock the file
> from one packet to the next.
>
> Shirley, this sort of thing has been done before (?).
> Pointers?
>
> Thanks!
> --don


--
Gemaakt met Opera's revolutionaire e-mailprogramma:
http://www.opera.com/mail/
(remove the obvious prefix to reply by mail)
From: D Yuniskis on
Hi Ignacio,

Ignacio G. T. wrote:
> El 08/03/2010 20:34, D Yuniskis escribi�:
>> Hi,
>>
>> I'm looking for ideas for a lightweight (yet robust)
>> autoupdate protocol for a family of network clients
>> I'm designing.
>
> [...]
>
>> Another approach is to *store* the fingerprint on the
>> server in a uniquely accessible manner (e.g., use
>> a file name like MAC.fingerprint). But, that represents
>> a duplication of data (pet peeve of mine) which makes
>> it at risk for getting out of sync.
>
> You could embed the fingerprint inside the image, at a reserved space in
> its beginning.

I *think* this is probably the best approach. It pushes all the
"special processing" into the activity that "creates an image"
instead of having to burden the system that *hosts* the image
or the individual responsible for putting the image in place.

I still have to consider how to ensure the file is locked
during the update (so it can't be removed or replaced)
but that will tend to be driven by the choice of transport
protocol.
From: D Yuniskis on
Hi Boudewijn,

Boudewijn Dijkstra wrote:
> Op Mon, 08 Mar 2010 20:34:53 +0100 schreef D Yuniskis
> <not.going.to.be(a)seen.com>:

[snips]

>> - Unattended, persistent operation. A device shouldn't
>> require hand-holding from a user to get itself into a
>> working configuration. It is acceptable (though not
>> *desireable*) to withold its normal functionality
>> from the user while updating *or* recovering from a
>> botched upgrade. But, it must be able to eventually
>> "right itself".
>>
>> - I don't want to have to *tell* the devices that they
>> need to be updated. The user shouldn't even be aware
>> that this is happening. I.e., the devices should be
>> able to examine/query the "current images" to see if
>> they coincide with *their* images.
>>
>> - I should be able to tailor an image to a *particular*
>> device (i.e., an *instance* of a device; not just a
>> "model number").
>>
>> - Images need to be signed so they can't be forged.
>>
>> - The protocol can't be spoofed by "unfriendlies".
>>
>> - The protocol should be as light as possible -- but
>> no lighter! ;-)
>>
>> - Minimize unnecessary network traffic as well as
>> load on the server (the goal is for the user *not*
>> to notice this activity -- though I am not trying
>> to "keep it secret")
>>
>> So, all I should have to do is put "current images"
>> on the user's server and wait for each device to
>> discover the image and update itself accordingly.
>>
>> Another approach is to *store* the fingerprint on the
>> server in a uniquely accessible manner (e.g., use
>> a file name like MAC.fingerprint). But, that represents
>> a duplication of data (pet peeve of mine) which makes
>> it at risk for getting out of sync.
>>
>> For example, updating the image and forgetting to update
>> the fingerprint;
>
> That's a bug.

That's "human nature" :> I.e., part of the problem is
anticipating what sorts of things are going to "go wrong"
and designing the protocol so they have minimal impact.

>> or, a run-time race -- the device
>> examines the fingerprint, sees that it differs, starts
>> to download image but the image hasn't been updated
>> yet.
>
> How can the server know the fingerprint before it has
> been fully updated?

I was assuming the fingerprint is computed elsewhere
(i.e., part of building the image). So, you have
xxxxx.image and xxxxx.fingerprint (like xxxxx.md5).
(I'm trying not to make the server do much of anything
so I can use some generic host for that role).

So, if someone is responsible for copying these two
files onto the server (via ftp, etc.) and happens to
copy the fingerprint *before* the image, then it is
possible that the "device" could examine that fingerprint
(coincidentally) and make its download/update decision
before the actual image has been copied (uploaded to
the server)

>> Or, the image is updated but the fingerprint
>> is stale when the device examines it. As a result,
>> the image is NOT seen as "new".
>
> No biggy. The device will check again sometime, right?

Yes. But then the frequency at which the device
re-checks the server becomes more significant.
Ideally, I would "signal()" the devices when I
*knew* the new image (and fingerprint) was available.
But, that's another action that someone (or something)
must perform. More resilient if the devices see to their
own needs without needing external prodding.

>> [you could get around this if you implemented network
>> file locking -- but that is more complexity and leaves
>> open the possibility of stale locks, etc.]
>
> Have you considered your own simple protocol? E.g.
> * client identifies to server and asks for update since $TIMESTAMP
> * server says yes or no
> * if yes, start streaming

Yes, but that means I have to have something "special"
running on the server. I.e., a way of asking for
an update "since $TIMESTAMP", a way for the server to
respond, etc.

I am trying to do those things without developing any
special server-side tools (which would have to be ported to
whichever server hosted these images, etc.)

If, instead, I did something like:
- image file name is MAC address of device (so each device
knows which image it should be interested in) with
".image" extension
- fingerprint is MAC address of device with ".fingerprint"
(e.g., ".md5")
- device fetches fingerprint via TFTP (since it is a tiny
file, you can get the entire file in one packet!)
- check against device's *computed* fingerprint
- device decides (on its own!) that it needs the new image
- device fetches image using (some existing) protocol

This fits within the services offered by most machines.
It requires the "image builder" (person + software) to
create these two files (since the image is built by compiling
sources, it seems appropriate to burden that person with the
task of creating the fingerprint) and somehow get them onto
the server in the right place.

(this ignores security issues, spoofing, etc.)

>> This could be worked around by forcing the server to
>> recompute the fingerprint each time an image is added.
>> But, that still leaves a race window
>
> Only if the image is already accessible while the fingerprint isn't
> there yet. And why would you do that?

If the server is "recomput[ing] the fingerprint" from the
image, then the image is *there*. You would need to
make sure it wasn't yet visible to the "client".

E.g., create a "MAC" subdirectory called MAC.temp. Put image
in there. Compute fingerprint and put it in there, too.
Then, mv(1) the subdirectory to "MAC" (where it would be visible
to the client).

(this still leaves problems to resolve).

<frown> I'm just trying to figure out how to get something
for nothing! :>

>> *and* requires
>> the server to be aware of the introduction of the
>> new image file(s).
>>
>> The simplest compromise would seem to be having the
>> device track the timestamp of the image file and
>> check *that*. If changed, then *assume* the image
>> actually has changed (of course, touch(1)-ing the
>> image file would then force the device to consider
>> the image file as changed -- this could be an
>> advantage?). The device could then either
>> fingerprint the image itself *or* naively assume
>> it to be a new image and begin the (secure) update
>> procedure.
>>
>> Security then is another facet to be addressed. E.g.,
>> given that the devices *don't* have enough resources to
>> store an entire image before flashing, the protocol
>> would have to be interruptible. E.g., encrypted
>> packets so they can't be spoofed. But, accepting
>> the possibility that the entire image might not
>> become available "when needed" for the reflash.
>> I.e., fall back to a secure boot loader that
>> can do the update without the rest of the application
>> being available.
>>
>> Note that this loader should *not* restart the upload
>> but, instead, *continue* where it apparently left off,
>> previously -- even in light of any intervening power
>> cycles. This saves time, reduces flash wear and is
>> just "smarter", in general. :>
>>
>> But, it seems like this *still* requires server side
>> locking so the file isn't changed *while* it is being
>> doled out.
>
> Why would you do that? Each unique image should have a unique name.

Well, it depends on how you then inform the client of the
"right" file to access! I.e., you need something that maps
client ID's to image filenames.

And then you have to make sure that is updated and the whole
race issue with keeping that synchronous with the image/fingerprint
files.

(unless you link(1) a client-specific name to a particular
set of files, etc.)

There are lots of ways you *can* do this. I'm just looking
for one that is clean and free from as many hazzards as
possible. :<

So far, I think putting the fingerprint *in* the image is
the best approach. Then, maybe using something like
sftp to fetch it.

So, client *always* starts to fetch the image. After it has
the first portion of it (seems wisest to put the fingerprint at
the head of the image file so you can get to it quickly),
it extracts fingerprint and decides if it wants to continue the
sftp session -- followed by a flashing -- or abort it.

That way, if the file is deleted/renamed on the server, an
instance of it should still be "link(1)-ed" to the sftp session
(so it doesn't disappear in the middle of the xfer)

>> E.g., something like TFTP would be
>> inappropriate as it doesn't reliably lock the file
>> from one packet to the next.
>>
>> Shirley, this sort of thing has been done before (?).
>> Pointers?