|
@@ -3,18 +3,19 @@ $Id$
|
|
Draft Requirements for Automated Multidomain Support in SER
|
|
Draft Requirements for Automated Multidomain Support in SER
|
|
============================================================
|
|
============================================================
|
|
|
|
|
|
-
|
|
|
|
-Jiri Kuthan, iptel.org, January 2003
|
|
|
|
|
|
+Jiri Kuthan, Jan Janak
|
|
|
|
+iptel.org
|
|
|
|
+January 2003
|
|
|
|
|
|
|
|
|
|
Summary and Status
|
|
Summary and Status
|
|
------------------
|
|
------------------
|
|
|
|
|
|
-Currently, maintenance of multiple domains is a very manual process
|
|
|
|
-in SER -- one needs to introduce new SQL tables, change scripts and
|
|
|
|
-restart SER on introduction of a new domain. This memo summarizes
|
|
|
|
-requirements for automation of this process. The holy goal is to
|
|
|
|
-make domain provisioning as easy as manipulating list of supported
|
|
|
|
|
|
+Currently (ser version 0.8.10), maintenance of multiple domains is
|
|
|
|
+a very manual process in SER -- one needs to introduce new SQL tables,
|
|
|
|
+change scripts and restart SER on introduction of a new domain. This
|
|
|
|
+memo summarizes requirements for automation of this process. The goal
|
|
|
|
+is to make domain provisioning as easy as manipulating list of supported
|
|
domains via FIFO server in run-time. This memo currently ignores
|
|
domains via FIFO server in run-time. This memo currently ignores
|
|
current implementation status -- parts of it have been implemented
|
|
current implementation status -- parts of it have been implemented
|
|
in existing (auth, usrloc, registrar) or new (domain) modules.
|
|
in existing (auth, usrloc, registrar) or new (domain) modules.
|
|
@@ -23,98 +24,155 @@ Most of issues raised here come from private or [serhelp] discussions
|
|
with Jan and Juha -- forgive me if I missed something when I was
|
|
with Jan and Juha -- forgive me if I missed something when I was
|
|
compiling it.
|
|
compiling it.
|
|
|
|
|
|
-Call for Comments
|
|
|
|
------------------
|
|
|
|
-please, let me know if I missed something. If you are aware how the
|
|
|
|
-individual requirements have been implemented, just put it in there.
|
|
|
|
-
|
|
|
|
|
|
|
|
Requirements
|
|
Requirements
|
|
------------
|
|
------------
|
|
|
|
|
|
-a) when a request comes, it needs to be understood, whether it belongs
|
|
|
|
|
|
+a) Identification of Served Domains
|
|
|
|
+
|
|
|
|
+ when a request comes, it needs to be understood, whether it belongs
|
|
to one of maintained domain, or shall be forwarded somewhere else;
|
|
to one of maintained domain, or shall be forwarded somewhere else;
|
|
- that's what SERVED_DOMAIN(URI) is good for; however, Before checking the
|
|
|
|
- domain ownership, one needs to translate domain name to a canonical
|
|
|
|
- form -- there may be many of names (domain name, host name, IP address,
|
|
|
|
- and other DNS aliases), out of which only the canonical one is used for
|
|
|
|
- domain processing; that's what CANONIZE_DOMAIN is good for
|
|
|
|
|
|
|
|
- it's good to be able to access (reload, or manipulate) the list of
|
|
|
|
- served domains in server's runtime -- use FIFO for that
|
|
|
|
|
|
+
|
|
|
|
+ SQL_TABLE: domain(domain)
|
|
|
|
+ SER module: domain
|
|
|
|
+ COMMANDS: is_from_local()
|
|
|
|
+ is_uri_host_local()
|
|
|
|
+
|
|
|
|
+ FIFO commands: domain_reload
|
|
|
|
+ domain_dump
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ comments: jh: "I use now 'is_uri_host_local'"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+b) Domain Name Canonization
|
|
|
|
+
|
|
|
|
+ situtations can occur when a domain is reachable under multiple
|
|
|
|
+ names; if that is the case, name canonization needs to be carried
|
|
|
|
+ out before the domain check in (a); this for example happens if
|
|
|
|
+ phones are connected, which use IP addresses in URIs.
|
|
|
|
|
|
SQL_TABLE: domains(name,canonical_name)
|
|
SQL_TABLE: domains(name,canonical_name)
|
|
- served_domains(name)
|
|
|
|
|
|
+ COMMANDS: canonize_domain
|
|
|
|
+
|
|
|
|
+ Note that such scenarios increase implementation and deployment
|
|
|
|
+ complexity. We thus better recommend using phones which do use
|
|
|
|
+ domain names.
|
|
|
|
+
|
|
|
|
+ Domain Name Canonization hasn't been implemented yet.
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+c) Multi-Domain User Lookup
|
|
|
|
+
|
|
|
|
+ user location module identifies users by username and canonical domain
|
|
|
|
+ name;
|
|
|
|
+
|
|
|
|
+ SQL_TABLE: location(user,domain,contact)
|
|
|
|
+ COMMANDS: lookup(table_name)
|
|
|
|
|
|
- COMMANDS: SERVED_DOMAIN(URI), CANONIZE_DOMAIN
|
|
|
|
|
|
+ To enable multi domain support in registrar, use the following
|
|
|
|
+ parameters: modparam("usrloc", "use_domain", 1) and
|
|
|
|
+ modparam("registrar", "use_domain", 1)
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
|
|
|
|
|
|
+d) Domain Verification in From HF
|
|
|
|
|
|
-b) secondly, one needs to be able to learn, whether request sender claims
|
|
|
|
|
|
+ one needs to be able to learn, whether request sender claims
|
|
a relationship to served domains in his From header field. to prevent
|
|
a relationship to served domains in his From header field. to prevent
|
|
unauthorized use of a served domain name in From, which -- if relayed
|
|
unauthorized use of a served domain name in From, which -- if relayed
|
|
by SER and rubber-stamped with its transport address -- could look
|
|
by SER and rubber-stamped with its transport address -- could look
|
|
trustworthy, one needs to authenticate the request sender
|
|
trustworthy, one needs to authenticate the request sender
|
|
|
|
|
|
- That's what SERVED_DOMAIN(FROM) is good for.
|
|
|
|
|
|
|
|
- COMMANDS: SERVED_DOMAIN(FROM)
|
|
|
|
|
|
+ COMMANDS: is_from_local()
|
|
|
|
+ SER module: domain
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
|
|
+ Note: If (b) can occur, canonization should take place first
|
|
|
|
|
|
-c) user location module identifies users by username and canonical domain
|
|
|
|
- name; a failure to canonize domain name prior to usrloc lookup results
|
|
|
|
- in an unseccessful lookup, if domain name in request is not canonical
|
|
|
|
|
|
|
|
- SQL_TABLE: location(user,domain)
|
|
|
|
|
|
+e) Username Verification
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-d) users may display one or more names legally in From header fields;
|
|
|
|
|
|
+ users may display one or more names legally in From header fields;
|
|
for example, a gateway operator is committed by law to forward only
|
|
for example, a gateway operator is committed by law to forward only
|
|
- user names (phone numbers) to PSTN which are owned by that user;
|
|
|
|
|
|
+ user names (phone numbers) to PSTN which are "owned" by that user;
|
|
it is thus important to be able to check whether a pair {digest_id,
|
|
it is thus important to be able to check whether a pair {digest_id,
|
|
From user name} is valid; there may be many of these pairs (i.e.,
|
|
From user name} is valid; there may be many of these pairs (i.e.,
|
|
there may be N valid Froms for 1 digest id); digest id may or may
|
|
there may be N valid Froms for 1 digest id); digest id may or may
|
|
not be the same string as From; (the second case for example
|
|
not be the same string as From; (the second case for example
|
|
occurs when an ISP already has a user database, he wants to reuse
|
|
occurs when an ISP already has a user database, he wants to reuse
|
|
for authentication, but wishes users to show their "phone numbers"
|
|
for authentication, but wishes users to show their "phone numbers"
|
|
- in From); That's what CHECK_FROM is good for.
|
|
|
|
|
|
+ in From);
|
|
|
|
+
|
|
|
|
+ Similar practise should apply to validation of To header field for
|
|
|
|
+ registrations. Otherwise, nothing would prevent users with valid
|
|
|
|
+ credentials to claim someone else's address in To and grab all his
|
|
|
|
+ incoming requests.
|
|
|
|
+
|
|
|
|
+ SQL TABLE: uri(user, domain, uri_user)
|
|
|
|
+ SER module: auth
|
|
|
|
+ COMMANDS: check_from
|
|
|
|
+ check_to
|
|
|
|
|
|
- SQL TABLE: valid_user{digest_id, realm, user_from}
|
|
|
|
- (or multiple user_from values may be alternatively part
|
|
|
|
- of subscriber table too)
|
|
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
|
|
+ if you use modparam("auth", "use_uri_table", 1) then uri table will
|
|
|
|
+ be used to map From or To username to a generic one and the generic
|
|
|
|
+ username will be compared to digest credentials username. If you do
|
|
|
|
+ not use the parameter, From or To username and digest credentials
|
|
|
|
+ username must be same.
|
|
|
|
|
|
-e) users need to be challenged with a proper realm; to automate this process,
|
|
|
|
|
|
+f) Generating Realm in Digest Challenges
|
|
|
|
+
|
|
|
|
+ users need to be challenged with a proper realm; to automate this process,
|
|
one can generate realm out of domain names in requests; xxx_challenge should
|
|
one can generate realm out of domain names in requests; xxx_challenge should
|
|
then use domainname in From HF as realm; the only exception is www_challenge,
|
|
then use domainname in From HF as realm; the only exception is www_challenge,
|
|
- in which case To HF is to be used for REGISTERs (not proxy_challenge, though)
|
|
|
|
|
|
+ in which case To HF is to be used for REGISTERs (not proxy_challenge, though);
|
|
|
|
+----?? does he do that??--------
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ACTION: {proxy|www}_challenge(AUTO);
|
|
|
|
+
|
|
|
|
+ The function accepts realm as the first parameter, if you use an
|
|
|
|
+ empty string "" then the realm will be extracted from From or To
|
|
|
|
+ header field (depending on function used and message type).
|
|
|
|
|
|
- If having (realm==domain name) is for some reasons too limiting, the
|
|
|
|
- served_domains table should include realm name associated with a given domain.
|
|
|
|
|
|
+ Note: If having (realm==domain name) is for some reasons too limiting, the
|
|
|
|
+ served_domains table should include realm name associated with a given domain.
|
|
|
|
+ Hopefully, there is no case for such automated realm generation.
|
|
|
|
+ Not implemented, realm must be equal to domain name if f) is used.
|
|
|
|
|
|
- If some phones can still only handle only IP and put them in
|
|
|
|
- From/To, one could still use the domains table for canonization
|
|
|
|
- prior to sending out the realm. (credentials based on a non-canonical
|
|
|
|
- domain name will not match the subscribers table otherwise)
|
|
|
|
|
|
+ Note: if (b) can occur, canonization should take place first.
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
|
|
|
|
-f) users need be authenticated properly; that takes in multi-domain
|
|
|
|
|
|
+g) Verifying Digest Credentials
|
|
|
|
+
|
|
|
|
+ users need be authenticated properly; that takes in multi-domain
|
|
environment looking up their entry in subscriber database correctly;
|
|
environment looking up their entry in subscriber database correctly;
|
|
the entry is identified by digest username (without domain name if
|
|
the entry is identified by digest username (without domain name if
|
|
present) and realm; if credentials are hashed, one needs to maintain
|
|
present) and realm; if credentials are hashed, one needs to maintain
|
|
and verify two hashes: one for users putting domain name in digest
|
|
and verify two hashes: one for users putting domain name in digest
|
|
id and one for users not doing so
|
|
id and one for users not doing so
|
|
|
|
|
|
- IMPLEMENTATION STATUS: ???
|
|
|
|
|
|
+ ACTION: {proxy|www}_authenticate(AUTO);
|
|
|
|
+
|
|
|
|
+ Comment: jh: the authenticate functions check that to/from matches
|
|
|
|
+ digest realm (which integrates (d))
|
|
|
|
+
|
|
|
|
+--------???----------
|
|
|
|
+ If there is a domain name in username in digest credentials, it
|
|
|
|
+ will be extracted and used as domain. realm parameter if digest
|
|
|
|
+ credentials cannot be used to pass domain because it is not
|
|
|
|
+ protected by the digest (username is protected). realm parameter in
|
|
|
|
+ digest credentials is used only to identifiy which credentials in
|
|
|
|
+ the message belong to the server.
|
|
|
|
+--------???----------
|
|
|
|
+
|
|
|
|
|
|
-g) aliases are same as usrloc -- now, they are looked by
|
|
|
|
- name and domain name
|
|
|
|
|
|
+g) User Aliases
|
|
|
|
+
|
|
|
|
+ aliases are same as usrloc -- now, they are looked by name and domain name,
|
|
|
|
+ that's it.
|
|
|
|
|
|
To-Do
|
|
To-Do
|
|
-----
|
|
-----
|
|
@@ -132,31 +190,42 @@ manipulate domains, served_domains and valid_user.
|
|
Script Example:
|
|
Script Example:
|
|
----------------
|
|
----------------
|
|
|
|
|
|
-/* does it belong to any of my served domains ? */
|
|
|
|
-canonize_domains(); /* 195.37.77.101 ->iptel.org */
|
|
|
|
-if (my_domain("uri")) {
|
|
|
|
- if (method=="REGISTER") {
|
|
|
|
- if (!www_authenticate()) {
|
|
|
|
- www_challenge("" /* realm from request HFs */...
|
|
|
|
- break;
|
|
|
|
- };
|
|
|
|
- save_contacts();
|
|
|
|
- break;
|
|
|
|
- };
|
|
|
|
- if (!lookup()) {
|
|
|
|
- sl_send_reply("404", "NotFound");
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/* does someoneclaimto belong to one of our served domain? prove it! */
|
|
|
|
-if (my_domain("from")) {
|
|
|
|
- if (!proxy_authenticate()) {
|
|
|
|
- proxy_challenge("" /* realm from request HFs */...
|
|
|
|
- break;
|
|
|
|
- };
|
|
|
|
- if (!valid_from() ..../* can user "jiri" have 7271 in from? */
|
|
|
|
- sl_send_reply("500", "Forbidden");
|
|
|
|
- break;
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
|
|
+ modparam("usrloc", "use_domain", 1)
|
|
|
|
+ modparam("registrar", "use_domain", 1)
|
|
|
|
+ modparam("auth", "use_uri_table", 1)
|
|
|
|
+ modparam("auth", "use_domain", 1)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ /* does it belong to any of my served domains ? */
|
|
|
|
+ canonize_domains(); /* 195.37.77.101 ->iptel.org */
|
|
|
|
+ if (is_uri_host_local()) {
|
|
|
|
+ if (method=="REGISTER") {
|
|
|
|
+ if (!www_authenticate("")) {
|
|
|
|
+ www_challenge("" /* realm from request HFs */...
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ if (!check_to()) ..../* can digest-id "u123" register as "jiri"? */
|
|
|
|
+ sl_send_reply("500", "Forbidden");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ save("location");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ if (!lookup("location")) {
|
|
|
|
+ sl_send_reply("404", "NotFound");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /* does someoneclaimto belong to one of our served domain? prove it! */
|
|
|
|
+ if (is_from_local()) {
|
|
|
|
+ if (!proxy_authenticate("")) {
|
|
|
|
+ proxy_challenge("" /* realm from request HFs */...
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+ if (!check_from() ..../* can user "jiri" have 7271 in from? */
|
|
|
|
+ sl_send_reply("500", "Forbidden");
|
|
|
|
+ break;
|
|
|
|
+ };
|
|
|
|
+
|