A proposal for RadioTag authentication and authorization

16 views
Skip to first unread message

Sean O'Halpin

unread,
Mar 11, 2011, 12:52:33 PM3/11/11
to RadioTAG developers
Hi,

Please find below our preliminary notes on our proposed authentication
and authorization protocol for RadioTag.

These notes have been prepared by Chris Lowis and myself on behalf of
BBC R&D.

For each of the scenarios described below, we have generated message
sequence diagrams, named after their respective scenarios, which fill
in the details. You'll find it easier to follow the narratives with
the diagrams.

* Our proposed authorization protocol

We are looking at the situation where a person presses a tag button on
a hybrid FM/IP-connected radio and wants a web service to (at the very
least) record the time and station they're listening to under their
own personal account.

To ensure that only the owner can update their account, we need to
authorize the radio. To do that, we first need to authenticate it.

In this, we're attempting to follow the OAuth 2.0 specification, in
particular in relying on an authenticated Token as the means of
authorization. We actually use only a small portion of the
specification
(http://tools.ietf.org/html/draft-ietf-oauth-v2-13#section-4.4) in
which a client obtains an authorization Token in response to
presenting a client credentials. How we obtain those credentials is
outside the OAuth 2.0 spec but comprises the bulk of what we discuss
here.

In the following discussion, we look at various scenarios to
investigate the robustness of our proposed authorization protocol:

- what happens when you press the tag button on a brand new radio,
enter all the required details correctly and end up with a tag on a
website (the 'happy path')
- what happens when you make mistakes trying to set up radio tagging
- what happens when you sell or lose the radio
- what happens when a hacker successfully spoofs the identity of the
radio

** The Radio

We assume the Radio has a dedicated Tag button, that you can enter
numbers between 0 and 9 and that it can display up to 32
characters. We also assume it has a means to generate new unique
Device IDs and that it can store at least a small amount of
information for an extended period of time.

** The web services

There are three web services involved: the Tag Service itself, an
Authorization Service and a Web Front End which itself requires an
authenticated login.

The Web Front End, Authorization Service and Tag Service all trust
each other to the extent of the information exchanged between them and
the services they can call upon from each other.

*** The Web Front End (WFE)

The Web Front End represents the whole 'user experience' of the site
where you set up an account, log in, view your tags, etc. We assume
that some other mechanism (a sign up/log in form, or Facebook Connect
for example) manages the authentication of accounts on this service.

*** The Authorization Service

The Authorization Service manages the authentication and authorization
of devices like radios. Note that this service does /not/ manage the
authentication of user accounts. We assume that happens elsewhere, as
explained in the Web Front End section above.

*** The tag service

The Tag Service is where tags can be added, listed and deleted. It
requires that the client has a valid Authorization Token. How the
client gets that Token is the subject of the protocol we discuss
below.

*** A note on Authentication vs Authorization

Just to be clear about the difference between authentication and
authorization. Authentication involves establishing the identity of a
client. Authorization is the process of granting permissions to
clients to allow them to do things. Together they ensure that only
clients who really are who they say they are can do the things they're
allowed to do.

In our setup, authentication is used to associate a radio with a
person's account and hence with the set of tags they create using that
radio.

Authorization is used to enable the device to add new tags to that
set.

** The scenarios

In the scenarios described below, we describe how a Person can
securely authenticate a Device (in this case a Radio) to an
Authorization Service that grants a Token to that Device. The Token
allows it to interact with a Tag Service. Once the Token is granted to
the Device, we assume that it can be used to both identify and
authorize client requests.

We also look at what happens in the event of mistakes, change of
ownership or malicious attempts to spoof a Device.

** Scenario 1: The 'Happy Path': Alice successfully creates a Tag

Diagram: http://dl.dropbox.com/u/909897/radiodns/happy.png

Alice pushes the Tag button on her Radio for the first time. In
response the Radio sends a Tag request to the Tag Service. Since this
is the first the Radio has made, the request is made without an
accompanying token.

The Tag Service consults the Authorization Service, which responds
with an unauthorised message, since no token is present. This
information is then given to Alice in the form of a message on her
Radio prompting her to register, accompanied by the Device ID and a
URL where she can register. The device then waits for a PIN to be
entered.

Alice reads the Device ID from the Device and visits the URL in a
browser. She creates an account (out of the scope of this protocol)
and is prompted to enter the Device ID. Upon doing so she is given a
(short) PIN number. Meanwhile the Device ID and PIN are stored on the
Authorization Service and associated with Alice's account.

Alice enters the PIN into her Radio. The Radio sends a request to the
Authorization Service with the Device ID and the PIN number. The
Authorization service responds with a Token, and associates this with
the details for Alice's account. The Token is stored in the Radio to
be sent along with future Tag requests.

When the Token is received the Radio again makes a Tag request to the
Tag Service with the parameters from when Alice first pressed the Tag
button. This time however, the Token is included with the request. The
Tag Service again makes an authorization request to the Authorization
Service which this time succeeds and the Tag is stored in the Tag
Service. The Tag Service responds with an "OK" message, which is
relayed via the Radio to Alice so that she knows the Tag request was
successful.

Subsequent Tag requests for this service succeed with a simple push of
the Tag button as long as the Token remains valid. Alice, or the
Authorization Service have the option to revoke the token at any time
to prevent further Tags being stored for this Radio.

** Scenario 2: Alice makes mistakes in trying to register her Radio

Diagram: http://dl.dropbox.com/u/909897/radiodns/mistakes.png

*** Alice pushes the Radio tag button & gets the Radio Device ID

The first two steps in this scenario are exactly the same as the happy
path scenario: Alice pushes the Tag button and, as the Radio is
unregistered, is prompted to enter the PIN.

*** Alice incorrectly registers the Radio

At this point Alice makes a mistake: she visits the Web Front End to
register the Radio but types in the wrong Device ID. The Authorization
Service has no way of checking the validity of Device IDs, so it
accepts the registration and returns a PIN.

**** Comments

We have chosen this way (no Device ID validation) over two
alternatives:

- a) Having a pre-populated database of all valid client ids
- b) Registering the device ID on first encounter

We believe that a) is impractical and anyway means that anyone with
access to such a database (i.e. the entire radio industry) could spoof
devices

While b) would allow us to reject attempts to register a device that
has not been seen, it also means that we would have to create a record
for every request containing a previously unseen device id. As these
records would be created anonymously, this leaves us too open to DOS
attacks (via resource exhaustion)

By creating the record on registration, although allowing a record for
a non-existent device, that record is associated with a user account
and can be created only via an authenticated route.

*** Alice enters the PIN for a non-existent Device ID

Alice enters the PIN. The Radio then requests a Token from the
Authorization Service using the (correct) Device ID and PIN (for a
different Device ID) as credentials.

The Authorization Service checks the credentials and discovers that it
has no record for the given Device ID. It responds with an "Account
not registered" error.

*** Alice registers the Radio

Alice realizes her mistake and revisits the Web Front End to register
her Radio again. This time she gets it right and receives another PIN
to enter.

*** Alice enters the incorrect PIN

Alice is not having a good day. She makes a mistake entering the PIN
number on the Radio. The Radio now requests a Token from the
Authorization Service, this time with (correct) Device ID and
(incorrect) PIN. The Authorization Service finds the record, rejects
the request as the credentials are incorrect, returning a "No match
for PIN" error.

The Radio responds to this error by asking for the PIN again.

*** Alice enters the correct PIN

This time Alice gets it right. She enters the correct PIN. We're now
back on the happy path. The Radio now completes the Tag request
successfully.

** Scenario 3: Alice revokes authorization then sells her Radio to Bob

Diagram: http://dl.dropbox.com/u/909897/radiodns/sold.png,
http://dl.dropbox.com/u/909897/radiodns/sold_001.png

After successfully tagging with her Radio, Alice decides to sell
it. Before she hands it over, she revokes its authorization from the
Authorization Service via the Web Front End. Revoking authorization
could also be done directly from the device using the Token as
authorization.

Bob now gets the Radio and attempts to create a Tag. The Radio still
has a Token, but the Authorization Service finds that it is no longer
valid and so refuses authorization.

Bob now registers the Radio as in the happy path scenario and ends up
successfully creating a Tag under his own Account. Note that the
Device ID has stayed the same throughout this scenario.

** Scenario 4: Charlie attempts to Tag to Alice's account

Diagrams: http://dl.dropbox.com/u/909897/radiodns/attack1.png,
http://dl.dropbox.com/u/909897/radiodns/attack1_001.png,
http://dl.dropbox.com/u/909897/radiodns/attack1_002.png

In this scenario we consider an attack from a malicious user, Charlie,
wishing to impersonate another user Alice.

Alice pushes the tag button on her Radio and follows the sequence
described in the Happy scenario until the point at which she reads the
Device ID from her Radio.

At this point, a malicious user Charlie, acquires Alice's Device ID
through some nefarious means - reading it from her device, or by
guesswork. He has a Hacker Device, either a physical Radio or
something which can act like a Radio by making the same API calls to
the service. He enters Alice's Device ID into his Hacker Device.

Charlie then proceeds to the Web Front End to register the Hacker
Device with the Device ID he stole from Alice. The Authorization
Service issues a PIN number and associates it and the stolen Device ID
with Charlies account. The PIN number is then returned to Charlie via
the Web Front End.

Charlie enters the PIN number into his Hacker Device and is issued
with an Authentication Token by the Authorisation Service. He can now
Tag using this token. Note however that all Tags that he creates are
stored under his account, not Alice's, on the Tag Service.

Alice, meanwhile, unaware of the attack proceeds to the Web Front End
to register her radio. When she enters the Device ID the Web Front End
informs her that the Device ID has already been used by another
Radio. She is requested to generate a new Device ID on her Radio, by
triggering a "factory reset".

Alice resets her Radio and then presses the Tag button again. She
follows the registration process as in the Happy scenario, this time
with a new Device ID. The registration is successful and she can Tag
as normal. Charlie meanwhile continues to Tag but is only ever adding
Tags to his account.



We welcome any and all feedback.

Regards,

Sean O'Halpin
Senior Software Engineer
BBC R&D Prototyping

Andy Buckingham

unread,
Mar 14, 2011, 5:29:16 AM3/14/11
to radiotag-...@googlegroups.com
Firstly, can I say a special thank you to Chris and Sean at the BBC
for their time and efforts so far.

There were some critical flaws identified in the last draft proposal
and their suggestions to overcome these issues are well thought
through.

After reviewing their proposals carefully, I have the following comments:

** Requirement for authentication and authorisation before first tag

We had previously discussed a multi-tiered methodology for tagging
where "box fresh" a device could tag without having to register. As
acknowledged by Sean and Chris this leaves a broadcaster prone to
flooding and resource exhaustion attacks, blindingly accepting and
storing data every time a device (valid or otherwise) requests so.

If we did allow any new device to submit tags straight away it could
be exploited by a 3rd party randomly generating device IDs and
submitting tags. Furthermore, if they hit the same ID as an existing
device that has yet to be authenticated and switch to using the new
token authorisation they could submit tags on that devices behalf.

That's not to say these risks could be minimised. One way this could
be eased is to hold those devices in a soft state, keeping those
records for a relatively short amount of time before being purged. In
addition, flood prevention could be imposed when a large number of
"unique" devices tag from a single IP, for example.

What I'd like to see is a careful use of language in the specification
to that there is nothing to stop a broadcaster implementing their
servers to behave in this way. I think it would be interesting to
allow options to exist, probably with attention drawn to the security
benefits of the least exploitable method. Thoughts?

** OAuth2 specification

As the OAuth2 specification is still draft, do we need to stick a flag
in the sand and say which version we should use? As stated:

> We actually use only a small portion of the specification
> (http://tools.ietf.org/html/draft-ietf-oauth-v2-13#section-4.4) in
> which a client obtains an authorization Token in response to
> presenting a client credentials.

Therefore am I right in thinking we actually utilise the methodology
of OAuth2 but, by explicitly defining the process in Tag, snapshot it
at the point of capture. Rather we are using the methodology of OAuth2
instead of declaring that a tag server should support OAuth2?

Whilst on the topic of OAuth2, it may be beneficial to alter some of
the language we've used within Tag to ease understanding. For example
in the realm of OAuth, our UDI or "Device Identifier" is actually a
"Client Identifier". I actually prefer this term as RadioTAG is just
as likely to be implemented in software (such as a smartphone) as it
is a hardware radio device. Therefore "Client" is a much more suited
term of reference in my opinion.

** The use of Device/Client ID as part of the authorisation process

Because the OAuth implementation has a requirement on the user keying
the client identifier read from the client screen in to the web front
end the previously proposed use of a UUID poses increased complexity
where the user has to copy a 32 digit number (hyphens could, at least,
be pre-populated).

If we looked to the use of a shorter ID we run the risk of collision
across multiple vendors. However, if we move to using a technology
such as OAuth between service providers for sharing user data rather
than client data, there is no specific requirement for client identity
to be unique outside the scope of any single service provider.
Therefore, we could propose service provider issued client IDs. Rather
than being a client ID it's more of a temporary token, issued to any
device that doesn't have an authorised token in memory. Once true
authorisation has been performed, the temporary token is terminated
and no longer valid.

Because this token only needs to be unique within a single providers
scope, we can greatly simplify it making it easier for an end user to
copy. If we use a base 36 number of 6 digits, we have an available
pool of 2.18 billion possible values. If clients are specified to
always accept and update a new incoming temporary ID on any
transaction until authorised with a proper token, it is possible to
recycle and have short lifetimes on the temporary tokens to avoid an
exploit exhausting the available tokens as discussed in other similar
attacks.


Thanks again.


A

--
Andy Buckingham
RadioTAG Application Team Lead
RadioDNS Project and Global Radio (UK)

t: +44 (0)117 900 5357
e: andy.bu...@radiodns.org
w: http://radiodns.org/

Follow the RadioDNS Project via Twitter: @radiodns

Kat

unread,
Mar 15, 2011, 1:35:49 PM3/15/11
to RadioTAG developers

This looks really good. A few things that occurred to me while reading
(apologies if they're already covered):

Scenario 3: Alice revokes authorisation then sells her radio to Bob
- can a single user own and authenticate multiple devices?
- can a single device be authenticated by multiple user accounts?

Scenario 4: Charlie attempts to tag to Alice’s account
- the hack here seems to be Charlie replacing Alice’s tags with his
own, rather than tagging to her account. Should we consider what would
happen if Charlie tried to hack this account after Alice had
authenticated her device? ie used the same device ID to access and add
to her tags? Or does OAuth only allow 1 device <> 1 account, and
therefore precludes this from happening?

Kat
> has a Token, but ...
>
> read more »

Andy Buckingham (RadioDNS)

unread,
Mar 15, 2011, 5:43:40 PM3/15/11
to radiotag-...@googlegroups.com
Hi Kat,

Welcome to the group. I'll attempt to answer your questions based on
my understanding of the recent proposal, will anyone else who feels
this doesn't match up with their interpretation feel free to question
and/or correct me.

> - can a single user own and authenticate multiple devices?

Absolutely. Based on my understanding of the proposal this "just
works". The user would go through the same process for each device,
but under the same user account on the web front end.

> - can a single device be authenticated by multiple user accounts?

This is a little out of the scope of the current proposal as it's very
much up to the service provider how they want to handle it. One way
would be for the SP to show an error when the user enters the device
ID, "Sorry this device is already registered to another user you can't
do this". Alternatively, they could add a button "Request permission
from owner?", which means the originating user is asked permission on
their next login/via e-mail etc. Once this confirmation occurs, the
device just works. They wouldn't need to go through the token process
as the device is already established.

The only time this would differ would be if devices have a concept of
multiple users on the device. In this instance we might want to
specify that the device treats each user in a "jailed" state, each
user has their own tokens/auth etc. Then, depending on which user is
"logged in" on the device they would authorise in the original way as
if they're the only person with the device doing it for the first
time.

> Should we consider what would happen if Charlie tried to hack this
> account after Alice had authenticated her device? ie used the same
> device ID to access and add to her tags? Or does OAuth only allow 1
> device <> 1 account, and therefore precludes this from happening?

Once authorised the token defines the relationship between device and
user account. Once the device is known by the service provider to be
in an authenticated state with a token issued, it should not allow
anyone to re-register it, unless the user authenticates in the web
front end and resets the auth procedure. This should make your
proposed attack suitably difficult! :)

Thanks for throwing these questions out to the group.


Andy.

Robin Cooksey

unread,
Mar 22, 2011, 12:51:17 PM3/22/11
to radiotag-...@googlegroups.com
Hi Everyone,

I've been following this discussion with interest, and looking at this from the perspective of a device manufacturer.

I have a couple of questions about the current discussion:

a) How is the device ID expected to be generated and what is its lifetime?

I guess this question may be rendered irrelevant by Andy's suggestion below that the device ID is in fact a temporary token which is generated by the service provider, for the purposes of displaying to the user, and allowing the authorisation process to provide the radio with an authenticated token.

However, my question was how is the device intended to generate a globally unique device ID, and what is the lifetime of the ID?
There was a suggestion that the device ID is cleared by a factory reset - and that after a factory reset a new device ID is generated. I can see this being difficult to implement - as it suggests that the device IDs are generated at run-time, rather than being statically allocated at radio manufacturing time (or derived from something that is - e.g. MAC address); and that they are required to be globally unique - even between different manufacturers.

So, if the device ID is something that the radio provides, is it possible for this to be static, and never change during the physical lifetime of the radio?
Provided that any tokens are cleared by a factory reset, what is the down-side of the device ID being the same?
When the user presses the tag button, there is no token stored, so the user will be prompted to register the device, using the device ID.
When they then enter the PIN on the radio, the radio then registers with the AuthService, and obtains a new token, associating the radio with the new users account.


b) My second question was related to the user experience when they attempt to create tags from more than one service.
When they first press the tag button, they are prompted to register, and associate their device with an account via the WFE, and the tag is created.
If they then tune to a different station, from a different service provider, and press the tag button - presumably the RadioDNS entry will point to a different service provider, and they will be expected to register again, with potentially a different WFE?
Is this the expected behaviour?

If so, how many different tokens would the radio have to store, and how does it determine which one to use? Should they be stored with the tag service hostname as a key?


Best regards,
Robin

Andy Buckingham (RadioDNS)

unread,
Mar 23, 2011, 5:48:26 AM3/23/11
to radiotag-...@googlegroups.com
On 22 March 2011 16:51, Robin Cooksey

<Robin....@frontier-silicon.com> wrote:
> a) How is the device ID expected to be generated and what is its lifetime?

The BBCs recent proposals were still loosely based on top of the
earlier drafts we had circulated around the team.

In those the device ID was intended to be a UUID, defined by many
existing specifications (ISO/IEC 11578:1996, ITU-T Rec. X.667 |
ISO/IEC 9834-8:2005 and RFC 4122). These were intended to be generated
on device reset and there would be a single identifier for the device.
One obvious consideration for this would be the feasibility of an
implementation of UUID generation on silicon.

The reason for allowing the device ID to be generated at run time and
changed on the device was in light of a user selling the device. If
the old user didn't release control of that identifier, the new one
may be unable to register - though this does depend slightly on how we
agree the interchange of tokens and device IDs work, as you suggest.

If at all possible I'd like to still keep open the possibility of a
service provider being able to implement very basic tagging without
the immediate need for registration. It is possible, however, that if
the service provider doesn't like tokens to a client but sees them as
an alternative access method instead of a client id, then a static
device ID could still be used. As you suggest, a device ID resets the
tokens and the user goes through a registration process again.

As device IDs are such a big part of the authorisation/pin code
process now the big thing I'd like to tackle is finding a suitably
unique and hard to guess identifier that is relatively short and
simple for a user to input. Robin, from a silicon point of view does
the service provider issue device identifier complicate things
significantly?

> b) My second question was related to the user experience when they attempt to create tags from more than one service.
> When they first press the tag button, they are prompted to register, and associate their device with an account via the WFE, and the tag is created.
> If they then tune to a different station, from a different service provider, and press the tag button - presumably the RadioDNS entry will point to a different service provider, and they will be expected to register again, with potentially a different WFE?
> Is this the expected behaviour?

Yes, currently this is expected behaviour. It is expected the device
keys the token(s) against the tag server address resolved from the SRV
lookup. For example, all of Global Radio's services might resolve to
tags.musicradio.com - this would only require a single token for all
Global radio stations. As you suggest we need to carefully think about
storage capabilities of devices and limitations associated. I would
consider defining a minimum number of token records as acceptable and
that if the device is capable of storing more it should do so.

We should probably stick a note here that this is an extreme
circumstance where the device is not affiliated with a 3rd party, for
example a manufacturers listening lounge service may exist as a
mediator and take responsibility for storing a lot of this data.
That's not to say we shouldn't find a reasonable solution for off the
shelf devices that don't have such support from a back end.


Andy.

Robin Cooksey

unread,
Mar 24, 2011, 8:28:20 AM3/24/11
to radiotag-...@googlegroups.com
Hi Andy,

> On 22 March 2011 16:51, Robin Cooksey
> <Robin....@frontier-silicon.com> wrote:
> > a) How is the device ID expected to be generated and what is its
> lifetime?
>
> The BBCs recent proposals were still loosely based on top of the
> earlier drafts we had circulated around the team.
>
> In those the device ID was intended to be a UUID, defined by many
> existing specifications (ISO/IEC 11578:1996, ITU-T Rec. X.667 |
> ISO/IEC 9834-8:2005 and RFC 4122). These were intended to be generated
> on device reset and there would be a single identifier for the device.
> One obvious consideration for this would be the feasibility of an
> implementation of UUID generation on silicon.


Thank you for the clarification. I can understand the motivation for using a UUID as the device ID to identify the device uniquely to the service provider, but as I understand the proposal, it is also used for the user to relate their account to the device via the WFE. I.e., the user types it into a web page.
This doesn't seem ideal - as you point out in another email - as the user would need to enter a 32 hex digit string.

> As device IDs are such a big part of the authorisation/pin code
> process now the big thing I'd like to tackle is finding a suitably
> unique and hard to guess identifier that is relatively short and
> simple for a user to input. Robin, from a silicon point of view does
> the service provider issue device identifier complicate things
> significantly?


Sorry, I'm not sure I quite understand your question.
Do you mean does it complicate things if the device identifier is issued by the service provider, rather than being created (and possibly reset after a factory reset) by the device?
I don't think it does - in fact, I think it may even be simpler (from the device perspective) if the service provider issues it to the device, rather than the device having to create it.

Depending on exactly what the device ID is used for (either just a one off process to get the token, or for future tag operations) then the device may need to store it, along with the token, for each service provider.


> > b) My second question was related to the user experience when they
> attempt to create tags from more than one service.
> > When they first press the tag button, they are prompted to register,
> and associate their device with an account via the WFE, and the tag is
> created.
> > If they then tune to a different station, from a different service
> provider, and press the tag button - presumably the RadioDNS entry will
> point to a different service provider, and they will be expected to
> register again, with potentially a different WFE?
> > Is this the expected behaviour?
>
> Yes, currently this is expected behaviour. It is expected the device
> keys the token(s) against the tag server address resolved from the SRV
> lookup. For example, all of Global Radio's services might resolve to
> tags.musicradio.com - this would only require a single token for all
> Global radio stations. As you suggest we need to carefully think about
> storage capabilities of devices and limitations associated. I would
> consider defining a minimum number of token records as acceptable and
> that if the device is capable of storing more it should do so.

Are the TagService and AuthService always guaranteed to be paired, or is there a circumstance that more than one TagService might share an AuthService?
If so, then presumably it's the AuthService that the token needs to be stored against by the device, rather than the TagService?


Robin

Chris Lowis

unread,
Mar 24, 2011, 10:07:49 AM3/24/11
to radiotag-...@googlegroups.com
On 24/03/2011 12:28, Robin Cooksey wrote:
> Thank you for the clarification. I can understand the motivation for using a UUID as the device ID to identify the device uniquely to the service provider, but as I understand the proposal, it is also used for the user to relate their account to the device via the WFE. I.e., the user types it into a web page.
> This doesn't seem ideal - as you point out in another email - as the user would need to enter a 32 hex digit string.

Hi Robin, thank you for taking the time to look at the protocol from a
device manufacturer's perspective, it's very useful to have your insights.

I think it would be useful for us to do a version of the protocol where
the device/client id is issued by the service provider. We didn't do
this to begin with as it adds another vector of complexity. Hopefully
we'll get chance to look at this next week.

One advantage of issuing the id from the service is that it would also
support devices that can have multiple users (with some kind of
user-switching support), each user on the device could then have their
own "device id" and therefore auth token.

> Are the TagService and AuthService always guaranteed to be paired, or is there a circumstance that more than one TagService might share an AuthService?
> If so, then presumably it's the AuthService that the token needs to be stored against by the device, rather than the TagService?

Yes, the AuthService is where device id and token would be stored and
associated (with an account).

We're currently working on a reference implementation that will also
hopefully demonstrate this in another way.

Thanks again,

Chris

Reply all
Reply to author
Forward
0 new messages