Merit Joint Technical Staff
Date Prev | Date Next |
Date Index |
Thread Index |
Author Index |
Historical
Re: Specifications for the validation server
- From: Richard S. Conto
- Date: Fri Oct 08 12:54:12 1993
> originally from: David Jelinek <34AAQ77@CMUVM.CSV.CMICH.EDU>
> originally to: mjts@merit.edu
> subject: Specifications for the validation server
> date: Fri, 08 Oct 1993 10:54:25 -0400
> ref: <931008.105425.EDT.34AAQ77@CMUVM.CSV.CMICH.EDU>
> --------
>Could someone please tell me where to find the specifications for the
>validation server? The C code would be nice too, but I really need the
>specifications as in descriptions of packets sent and received etc.
There complete source code for the Merit Authorization Server is
available via ANONYMOUS FTP from MERIT.EDU in "/pub/michnet/mnetauth.tar.Z".
In this compressed "tar" file is a file is a protocol description, in
"./doc/protocol.txt".
This server is going to be obsolete soon, because of the "NAS" work
(Network Access Server) is resulting in a "helper" protocol based on
Livingston's "radius" package, with enhancements.
I am enclosing this document.
--- Richard
--------------- "./doc/protocol.txt" -----------------------------
The Merit Authorization Mechanism
Protocol Description
Created July 24, 1989
by Richard S. Conto
Change History:
1989Jul24 (rsc) initial revision
1989Jul28 (rsc) remove 'at_hlhost', add 'at_service', make
certain parameters required, make 'at_service'
a boolean (no requests), describe host locator
interaction with user.
1990Sep05 (rsc) Update to current implimentation.
1991Oct01 (rsc) at_opercmd, at_servicelist, and othher updates
current configuration.
Protocol for Merit Network Authorization Service
(called from the Host Locator)
Round 2.0
Summary:
Currently, an unreliable, unsequenced datagram protocol
is the best transport service available for communicating
with Internet attached hosts. The earlier protocol required
a session with the authorizing (internet) host, which requires
a reliable, sequenced record protocol (the protocol was text
oriented, and the records were delimited by <eol>.) A re-design
of the protocol to make it "stateless" would eliminate the need
to design, build (and debug) a session layer on top of UDP, on
both MTS and the intended servers (BSD Unix systems.)
(There is a "Telnet" service available, but this would also
require building a telnet protocol engine on top of a BSD
"tcp" socket, and I wasn't able to quickly find sources for
a telnet server suitable for this.)
Proposal:
1.) That the new protocol be a "binary" protocol. (Parsing
a text protocol may be easy on MTS, but I'm not familiar
enough with whatever Unix grammar compilers that exist
that I feel confident about finishing this in a reasonable
time.)
2.) That each "packet" be entirely self contained. (i.e.:
it will contain both ID and PW.) It will be reasonable
to encrypt both ID and PW...
3.) That the protocol be extensible for future needs.
4.) That the protocol allow for an authorization server to
act as an agent for another administration (i.e.: a Merit
server acting to authorize for Ferris State.)
5.) That the host locator prompt for an authorizer also
prompt for an id, and include a way so that authorized, id,
and password be supplied on one line, and that id and
password can be supplied when an id is prompted for so
that users (and canned procedures) can quickly answer the
request for authorization. (Also, a syntax for HL requests
so that little prompting is required can be done as well.)
*** Host Locator User Interface (what the user 'types') ***********
There will be two different ways for a user (or program script)
to pass information to the host locator, either by keyword, or
by allowing the HL to prompt for further information. In the first
case (keyword), the user (or more likely script) will be able
to indicate at the "Which Host?" prompt (or %GRAB command) the
following:
> Which Host? HOST=hostname AUTHCODE=auth-host/id PW=password
> ***********************************************
>
> In this case, the host locator will NEVER prompt (even if
> requested to by the 'auth-host'.) It will always respond with
> the one-line message 'ALLOWED' or 'DENIED' (and if success, it
> will pass on the connection.) If the host locator gets a prompt
> request from the authorization server (auth-host), it will treat
> it as 'DENIED'.
In the other (prompt) case, the host locator may prompt as
follows:
> Which Host? hostname
> ********
> <service> authorization required. You must be authorized by
> a Merit certified host for access.
> Enter authorization code? auth-host/id [ [PW=]password ]
> ****************************
> Where <service> is the service the host locator needs to have
> validated, such as "Internet" or "Surcharge". (This also means
> that the host locator needs the concept of 'service' added to
> it's algorithms and tables.)
>
> "auth-host/id" is the Merit "authorization code". It may be derivable
> from the user's login id on the certified host "auth-host", but that is
> not necessary. The password may be provided at this point. If not, Merit
> will prompt for a password.
>
> Password? password
> ********
> A password must ALWAYS be supplied. Passwordless logins are not allowed to
> be certified by a Merit certified host. Similarily, "anonymous" mechanisms
> are not to be allowed.
>
> If more input is necessary, the protocol allows for prompting of further
> input. Obviously, this won't be possible in the very first example above.
>
> If the host locator gets a "prompt" or "prompt_blanked"
> request from the 'auth-host', it will use the prompt string
> supplied with the request to as a prefix/prompt and wait for
> input from the user.
The Host Locator and the Authorizing Host (Authorization Server)
will interact by sending data records to each other. In the case
where MTS is the authorization server, the Host Locator will open
a Merit/MTS server connection to MTS. All traffic will occur over
this connection, until one end or the other closes the connection,
or the Authorization Server sends a 'SUCCESS' or 'FAIL' status
message (when the authorization server will disconnect.) In the
case where an Internet attached host is the authorization server,
the Host Locator will open a connection to the TLI host and send
UDP packets to the internet host. It will initially time out after
30 seconds, or upon the receipt of an ICMP message indicating that
the network, host, or service is unavailable. (A 'service mapper'
was described once by a RFC... it may be necessary to use this
service mapper to determine what UDP port the authorization server
is listening to.) If the Host Locator receives a response, it will
use 3 times the round trip time for further timeouts (if any
further interaction is necessary.)
Also, a number of fields are required from the host locator,
such as ID, PW, TERMINFO, SERVICE and a few others. This will
allow the Host Locator to pre-assemble a request record once
containing this information, and then add any reply that are
prompted for. (The Host Locator must keep track of all replies,
and replace any replies that are re-prompted for.)
The authorization protocol I'm proposing will be structured as
follows (I'll use "C"-like definition of the data structures.) All
binary integers will be in "big-endian" form, which means (I
believe) that the most significant byte "comes first."
'authorize_t' has a 'sequence_id'. This id is used by the Host
Locator to match it's requests to the Authorization Host with
responses from the Authorization Host. Only the Host Locator may
change this value (which makes it safe for 'little-endian'
machines). When the Authorization Server gets a request from the
Host Locator, it must respond with the same 'sequence_id'. This
will allow the Host Locator to throw away old, duplicate responses.
(The Host Locator will quietly discard any responses that do not
have the 'sequence_id' it is waiting for.)
The following describes various types and data structures used
in the transaction protocol (request and response.) This is not
recommended as the internal representation of these fields within
the Host Locator or Authorization Server (although they may be
used if CPU cycles aren't a consideration ;-) ). This description
attempts to describe things at 'octet' (or byte) boundaries.
However, enumerated types and other data structures are used to
illustrate how the data works, in a more human-understandable
fashion.
/*
Type definitions and representations for the Merit Host Locator
Authorization Server protocol.
Some of these types may be already declared in standard libraries.
Use of those libraries is recommended. Their inclusion here is for
illustrative purposes. These definitions have not yet been tested
to see if they even compile, much less produce the correct
data structures and offsets.
******************************************************************
"int16" is a 2 byte integer. For some systems, this will be a
normal 'int', for others it might be a 'short int'.
*/
typedef int8 unsigned char; /* range 0 to 255, in an octet. */
typedef enum { at_ignore=0, at_id=1, at_pw=2,
at_billentity=3, at_charges=4, at_terminfo=5,
at_mincharge=6, at_balance=7, at_authid=8,
at_message=9, at_reply=10, at_prompt=11,
at_prompt_blanked=12, at_cantreply=13, at_status=14,
at_service=15, at_dest=16, at_binary=17,
at_done=18, at_setpw=19, at_userstatus=20,
at_opercmd=21, at_servicelist=22
} at_tag_t;
typedef enum { at_status_denied=0, at_status_bad_id=1, at_status_bad_pw=2,
at_status_bad_service=3, at_status_protocol_error=4,
at_status_internal_error=5 } at_status_kind;
typedef enum { false=0, true=1 } boolean; /* Simple true/false */
#define MAXSIZE 32767 /* Maximum size for MTS READ oper. */ \
-32 /* "authorize_t" overhead. */ \
-8 /* UDP overhead. */ \
-24 /* minimum IP overhead. */
struct
authorize_t {
int16 sequence_id, /* Arbitrary identifier... */
int8 version, /* A version number, starting at 1. */
int8 count, /* Number of elements (below) */
byte elements[MAXSIZE] /* octet array of tagged items */
};
typedef struct {
int8 len, /* Length of string, 0 .. 255 */
char text[255], /* Text of string, if len > 0 */
} string_t; /* Like Plus's character(0 to 255) */
typedef struct {
int8 id, /* For matching PROMPT with REPLY */
string_t str /* The prompt (and reply) */
} promptstr_t;
typedef struct { /* What follows in element field. */
int8 tag, /* What follows... */
union {
string_t str, /* for IGNORE, ID, PW, MESSAGE, AUTHID,
TERMINFO, CHARGES, BILLENTITY, DONE,
SERVICE, DEST, SETPW, USERSTATUS */
promptstr_t prompt, /* For PROMPT, PROMPT_BLANKED, BINARY, REPLY, and
SERVICELIST */
int16 num, /* For MINCHARGE, BALANCE */
int8 status, /* For STATUS (failure indicator) (at_status_kind)*/
u_char octet, /* CANTREPLY is a boolean. */
}
} element_t;
The elements can occur in any order. Each element is "packed"
to it's minimum size when it's addeded to the element array.
(I.e.: strings only take up "len+1" bytes.) All string values
are ASCII text, and are case insensitive... but the host locator
probably shouldn't convert things to upper or lower case.
Each "prompt" or "promptblanked" request must have a unique
identification number assigned (i.e.: '1' for 'ID', '2' for
'password', '3' for '*CKID ID', etc.) This identification is
passed back on the 'reply' from the Host Locator to the
Authorization Server, and is the only way to identify a particular
response (since the 'prompt' and 'prompt_blanked' are lost.)
Description of each tag:
"at_ignore" (tag value 0): This is a string value that can be
completely ignored. Treat it as a comment field.
... [ Bidirectional ] [ Optional ].
"at_id" (tag value 1): This is the ENCRYPTED id being checked
against. (The encryption mechanism has yet to be decided
upon. Something based on the MTS CRYPT() should be used, since
this can be de-crypted.
... [ HL -> AS ] [ Required ]
"at_pw" (tag value 2): This is the ENCRYPTED pw (for the id)
to check against. (See "at_id" for comments about encryption.)
... [ HL -> AS ] [ Required ]
"at_billentity" (tag value 3): This indicates what "administration"
handles authorization or billing. It should be present ONLY if
the authorization server is different from the billentity.
It allows one host to act as an authorizing agent for a group
that doesn't have a host of their own. (i.e.: a Merit Sun
acting as an authorizor for Central Michigan Univ, or Ferris
State.) (The billentity is ALWAYS included on the 'network id'
of a Host Locator approved connection.)
... [ HL -> AS ] [ Required if the 'billentity' is different
from the AS. ]
"at_charges" (tag value 4): This is the Merit "Charging
Entity", taken from the "CE=" field of the Merit Network
Rate Record. Currently, this has the values: "Telenet",
"Autonet", or "Merit". It indicates what organization or
unit is generating the charges. It's presence REQUIRES
that the Authorization Server respond with 'at_balance'.
... [ HL -> AS ] [ (obs) Required if present in Merit Rate Record. ]
"at_terminfo" (tag value 5): This is the MTS ANSWERBACK(long).
This allows some sort of independant tracing at the
Authorization Server of password failures or illegal usage
without necessitating checking through logs on MTS.
The one from MTS contains the MTS answerback prefixed with
the text "MTS:". The test programs prefix it with "TEST:".
The Hermes-Agent should prefix it with "HA(hostname):"
... [ HL -> AS ] [ Required ]
"at_mincharge" (tag value 6): This is the minimum estimated
charge to be incurred for 1 minute of use of this service.
... [ HL -> AS ] [ (obs) Required if 'at_charges' is sent ]
"at_balance" (tag value 7): This is the minimum balance available.
(Can be used by the HL to deny service, if the minimum
balance is too small.)
... [ AS -> HL ] [ (obs) Required in response to request with
'at_chargeentity' ]
"at_authid" (tag value 8): This is a character string containing
PRINTABLE ascii characters, excluding <space> (" "), <comma>
(","), and <equals> ("="). This token is used by the network
to identify a user for audit trails. It is also presented back
to the authorizing host when receipts and bills are produced for
charged services.
... [ AS -> HL ] [ ONLY if the authorization succeeds. NO AT_STATUS ]
"at_message" (tag value 9): A simple one-line string message
to be printed on the user's terminal by the HL. Multi-line
messages are printed by seperate "at_message" things, in
the order they occur.
... [ AS -> HL ] [ Optional ]
"at_reply" (tag value 10): This is the response to an "at_prompt"
or "at_prompt_blanked". This is sent from the HL to the
Authorization Server. The "reply" contains an identification
number, that corresponds to the "prompt" or "prompt_blanked"
that caused it. More than 1 reply to the same prompt is
explicitly disallowed. The Host Locator must keep track of
all replys, and must always transmit all known replies.
If prompted for an existing reply, it must replace that
reply with a new one obtained from the user.
... [ HL -> AS ] [ All current replies must be included ]
"at_prompt" (tag value 11): This is a prompting string (1
line of text only). It is originally sent from the
Authorization Server to the HL if the authorization server
needs more information. An identification field on the
prompt request is used to match it with it's reply.
Only the identification number in the 'at_prompt' identifies
it when the reply is returned to the Authorization Server.
'at_prompt' is treated as 'at_status' == false (fail), if
'at_canreply' was sent on the HL -> AS request. (In fact,
'at_status' = false should be sent instead.) The text string
included with 'at_prompt' (and 'at_prompt_blanked' below)
is used as an prefix/prompt string for requesting more
input from the user. The order of prompts presented to the
user is the same as the left-to-right order (low offset to
high offset) as encountered in the 'elements' array in the
'authorize_t' structure. 'at_prompt' and 'at_prompt_blanked'
preclude the presence of 'at_status' (and vice-versa.)
'at_prompt' is the ONLY way for the Authorization Server
to get more information from the Host Locator.
... [ AS -> HL ] [ Disallowed if 'at_cantreply', treated
as 'at_status' == false. ] [ Disallowed if 'at_status'
is present. ]
"at_prompt_blanked" (tag value 12): This is like "at_prompt",
except that any input typed by the user is not echoed, or
otherwise overprinted so that it can't be accidentally
revealed.
... [ AS -> HL ] [ Disallowed if 'at_cantreply', treated
as 'at_status' == false. ] [ Disallowed if 'at_status'
is present. ]
"at_cantreply" (tag value 13): This indicates that the HL
will be unable to respond to an "at_prompt" or an
"at_prompt_blanked". It only occurs when the Host Locator
processes a keyword 'HOST=hostname AUTH=auth-host' ...
request. This is so that machine scripts can easily
determine success or failure and don't need to check for
id/pw replacement prompting from the Authorization Server
(through the Host Locator.)
... [ HL -> AS ] [ Required ONLY for Keyword Requests. ]
"at_status" (tag value 14): If present, it indicates the reason for a
failure. No further interactions with the Authorization Server will
occur, and any connections may be closed. See "at_status_kind" above
for some of the reasons. A generic "at_status_denied" may be presented,
if that is the only information the server feels safe to present, but
Merit would like to know about id and pw failures, to assist in tracking
down problems.
... [ AS -> HL ] [ Disallowed if "at_prompt", "at_prompt_blanked", or
"at_authid" are present. ]
"at_service" (tag value 15): This string value indicates
what service the Host Locator is trying to get authorization
for. (Initial values might be "Internet", "Telenet",
"Autonet", "Merit", "UM-Laserwriter", and "UM-Dialout".)
... [ HL -> AS ] [ Required ]
"at_dest" (tag value 16): This is the "hostname" that
the host locator is trying to resolve (and gain access
to.) This name should be translated to uppercase.
... [ HL -> AS ] [ Required ] [ Translated to uppercase ]
"at_binary" (tag value 17): This field allows the Host Locator to
keep state information (such as password failure counts)
between exchanges with the authorization server. The authorization
server is not required to use this, but if it may use it if the
server trusts the Host Locator sufficiently. The "at_binary"
fields are themselves indexed, so that multiple state variables may
be stored in the Host Locator. The Host Locator itself does not
examine these values, but simply passes them back on subsequent
transmissions to the server.
[ AS -> HL, then HL -> AS ] [ HL is required to pass this back
if presented by the AS.]
"at_done" (tag value 18): This is like "at_cantreply" in that it
indicates that the HL will not be interacting with the AS again. It
requests that any running "daemon" process be terminated. (The daemon
process may be restarted.) This is to help clear out any resources the
authorization server may be using when they are no longer needed. This
tag is only sent when configured in the HL. It passes a string indicating
the "reason".
[ HL -> AS ] [ Configurable ]
"at_setpw" (tag value 19): This string offers a new password to the server.
This is a reserved value, and isn't implimented yet.
[ HL -> AS ] [ not implimented, reserved. ]
"at_userstatus" (tag value 20): This allows the Merit NOC to "disable" an
account for the purposes of "authorization". (I.e.: if a user reports to
the NOC that someone has stolen their password.) The string values
"enable", "disable", and "status" are required commands. An ID is
required, but a password isn't.
[ HL -> AS ] [ control function. ]
"at_opercmd" (tag value 21): This allows the Merit NOC to issue operational
commands to the authorization server. This function should make the
at_userstatus command obsolete, since at_userstatus is insecure.
[ HL -> AS ] [ control function. ]
"at_servicelist" (tag value 22): This is a list of service and octet pairs.
The client (the host locator) sends a list to be approved. The
server responds with the approved list. This allows the client to
determine which services of a list are allowed. The client may use the
octet value for any purpose. (Using the octets as a bit mask to be
logicaly 'or'ed together to determine a capability bit mask is
intended for this.)
[ HL <-> AS ]
Examples:
A Host Locator needs to determine access a Telenet user trying
to gain access to "umlib". The Host Locator prompts for an
authorizer/id/pw with, but only gets an authorizer and ID. It then
sends the following request to the authorizer:
authorize_t { '4242', '01', '06', /* Seq=16962, Ver 1, 6 Items */
{'01','03','6D7473' }, /* at_id = "mts" */
{'04','07','54656C65 6E6574'}, /* at_chargeentity = "Telenet"*/
{'05','31','41593233 2D583354 453B5445 40414E3B 54583032 3A4E4F4E
45202020 20333131 30333133 30303036 3220463D 30313031
'} /* at_terminfo =
"AY23-X3TE;TE@AN;TX02:NONE 311031300062 F=0101" */
{'06','0005' } /* at_mincharge = 5 cents. */
{'0F','03','54656C65 6E6574'}, /* at_service = "Telenet" */
{'10','05','554D4C49 42'} /* at_dest = "UMLIB" */
};
In the future, I'll show this as:
authorize_t { 16962, 1, 6,
{at_id, "mts" },
{at_chargeentity, "Telenet" }
{at_terminfo, "AY23-X3TE;TE@AN;TX02:NONE 311031300062 F=0101"}
{at_mincharge, 5}
{at_service,"Telenet"},
{at_dest,"umlib"}
}
The Authorization server host responds, indicating that a pw is
required (it responds to the initiating UDP port number, using the
same 'sequence id' number on the 'authorize_t' record as sent by the
HL.)
authorize_t { 16962, 1, 1,
{at_prompt_blanked, 1, "Password? "}
}
The Host locator then prompts the user for whatever the
authorization server requested. The HL doesn't really know what
it's prompting for... just the index number and the prompt string.
Note: We might want to use some reversible encryption here. The HL
changes (increases) the sequence ID (so the responses can be
correctly identified),
authorize_t { 16963, 1, 7,
{at_id, "mts"}
{at_chargeentity, "Telenet" }
{at_terminfo, "AY23-X3TE;TE@AN;TX02:NONE 311031300062 F=0101"}
{at_mincharge, 5}
{at_service,"Telenet"}
{at_dest,"umlib"}
{at_reply, 1, "mastercard"}
}
If the id/pw combination were invalid, the server could return
the following:
authorize_t { 16963, 1, 2,
{at_message,"Invalid id or password"}
{at_status, 0 }
}
Or, if the server wanted to re-try the pw, it could:
authorize_t { 16963, 1, 2,
{at_message,"Invalid password, please try again."}
{at_prompt_blanked, 1, "Password? "}
}
The Host Locator would discard the previous value of prompt #1,
prompt again from the user (using the supplied prompt string), and
send that result back... until prompted again for that same prompt
index.
Of course, if the id/pw combination were valid, the server would
return:
authorize_t { 16963, 1, 3,
{at_message, "You've got $101.56 ... go for it."}
{at_balance=10156} /* $101.56 */
{at_token, "WMTSMTS."}
{at_status, 1 }
}
****************************************************************
Example:
Here, the user supplied a password as well as an ID. The
interaction would be simpler.
authorize_t { 16962, 1, 7,
{at_id, "mts" },
{at_pw, "mastercard"}
{at_chargeentity, "Telenet" }
{at_terminfo, "AY23-X3TE;TE@AN;TX02:NONE 311031300062 F=0101"}
{at_mincharge, 5}
{at_service,"Telenet"},
{at_dest,"umlib"}
}
If the id/pw combination were invalid, the server could return
the following:
authorize_t { 16963, 1, 2,
{at_message,"Invalid id or password"}
{at_status, 0 }
}
Or, if the server wanted to re-try the pw, it could prompt:
authorize_t { 16963, 1, 2,
{at_message,"Invalid password, please try again."}
{at_prompt_blanked, 1, "Password? "}
}
Of course, the HL won't really know that it's prompting for a
password. The authorization server will have to know that an
explicit prompt #1 (for it's "Password? " prompt) overrides the
at_pw field.
authorize_t { 16962, 1, 8,
{at_id, "mts" },
{at_pw, "mastercard"}
{at_chargeentity, "Telenet" }
{at_terminfo, "AY23-X3TE;TE@AN;TX02:NONE 311031300062 F=0101"}
{at_mincharge, 5}
{at_service,"Telenet"},
{at_dest,"umlib"}
{at_reply, 1, "discovercredit"}
}
- - - - - - - - - - - - - - - - -
|