logo_kerberos.gif

Projects/Services4User

From K5Wiki
< Projects(Difference between revisions)
Jump to: navigation, search
(gss_acquire_cred_with_cred)
 
(30 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{project-early}}
+
{{project-rel|1.8}}
  +
 
Working code is in the [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/s4u users/lhoward/s4u] branch.
 
Working code is in the [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/s4u users/lhoward/s4u] branch.
 
<includeonly>[[Category: early stage projects]]</includeonly>
 
   
 
==Background==
 
==Background==
Line 13: Line 11:
 
Together, these extensions are referred to as Services4User, or S4U.
 
Together, these extensions are referred to as Services4User, or S4U.
   
The KDC will typically make some authorization checks before permitting the above: for S4U2Self, a flag on the service indicating that it is "trusted to authenticate for delegation" and, for S4U2Proxy, a set of server principals to which the service is permitted to delegate to. There is already some KDC-side support for these protocols in MIT Kerberos 1.7 (although supporting S4U2Proxy requires explicit backend support that is not included with the standard distribution, and S4U2Self does not support some protocol extensions Microsoft made in Windows 2008).
+
The KDC will typically make some authorization checks before permitting the above: for S4U2Self, a flag on the service indicating that it is "trusted to authenticate for delegation" and, for S4U2Proxy, a set of server principals to which the service is permitted to delegate to. (Note: the trusted to authentictae for delegation flag controls whether a service can use S4U2Self to get forwardable tickets, not whether it can use S4U2Self.)
  +
  +
There was already some KDC-side support for these protocols in MIT Kerberos 1.7 (although supporting S4U2Proxy requires explicit backend support that is not included with the standard distribution, and S4U2Self does not support some protocol extensions Microsoft made in Windows 2008). (Note: this is old information. See [http://k5wiki.kerberos.org/wiki/Projects/ConstrainedDelegation ConstrainedDelegation].)
   
 
This proposal is principally concerned with the client-side (or, more correctly, service-side) implementation of S4U, although we have also updated the KDC and kadmin to more completely support S4U2Self.
 
This proposal is principally concerned with the client-side (or, more correctly, service-side) implementation of S4U, although we have also updated the KDC and kadmin to more completely support S4U2Self.
Line 45: Line 43:
 
</pre>
 
</pre>
   
Flags for use with PA_S4U_X509_USER are also defined here, although as they are not exposed through any APIs they could be moved to k5-int.h:
+
Flags for use with PA_S4U_X509_USER are also defined in k5-int.h:
   
 
<pre>
 
<pre>
Line 66: Line 64:
 
==Proposed APIs==
 
==Proposed APIs==
   
I propose that the only public APIs are at the GSS-API layer. We will need to export krb5 APIs for GSS to use, and possibly the kvno tool (for testing); it's probably not necessary to indirect these through an kaccess, though.
+
The only public interface to Services4User is through GSS-API. We will need to export krb5 APIs for GSS to use, and possibly the kvno tool (for testing); it's probably not necessary to indirect these through an kaccess, though.
   
These APIs are defined in gssapi_ext.h and were designed by Nicolas Williams. There is presently no support for certificate-based protocol transition.
+
These APIs are defined in gssapi_ext.h and were designed by Nicolas Williams. Note: a mechanism need only implement gss_acquire_cred_impersonate_XXX(), as the mechglue implements gss_add_cred_impersonate_XXX() in terms of it.
  +
  +
There is presently no support for certificate-based protocol transition.
   
 
===S4U2Self===
 
===S4U2Self===
   
====gss_acquire_cred_with_name====
+
====gss_acquire_cred_impersonate_name====
   
 
<pre>
 
<pre>
 
OM_uint32 KRB5_CALLCONV
 
OM_uint32 KRB5_CALLCONV
gss_acquire_cred_with_name(
+
gss_acquire_cred_impersonate_name(
 
OM_uint32 *, /* minor_status */
 
OM_uint32 *, /* minor_status */
 
const gss_cred_id_t, /* impersonator_cred_handle */
 
const gss_cred_id_t, /* impersonator_cred_handle */
Line 88: Line 86:
 
</pre>
 
</pre>
   
This function uses <i>impersonator_cred_handle</i> to acquire a credential for <i>desired_name</i>. Only the initiator credential usage is supported by Kerberos. The returned credential can be passed into gss_init_sec_context().
+
This function uses <i>impersonator_cred_handle</i> to acquire a credential for <i>desired_name</i>. Only the initiator credential usage is supported by Kerberos. The returned credential can be passed into gss_init_sec_context(), and is a "proxy" credential (it can be used for constrained delegation without an explicit call to gss_acquire_cred_impersonate_cred(); think of it as equivalent to a delegated credential handle returned by gss_accept_sec_context()).
   
====gss_add_cred_with_name====
+
====gss_add_cred_impersonate_name====
   
 
<pre>
 
<pre>
 
OM_uint32 KRB5_CALLCONV
 
OM_uint32 KRB5_CALLCONV
gss_add_cred_with_name(
+
gss_add_cred_impersonate_name(
 
OM_uint32 *, /* minor_status */
 
OM_uint32 *, /* minor_status */
const gss_cred_id_t, /* impersonator_cred_handle */
 
 
gss_cred_id_t, /* input_cred_handle */
 
gss_cred_id_t, /* input_cred_handle */
  +
const gss_cred_id_t, /* impersonator_cred_handle */
 
const gss_name_t, /* desired_name */
 
const gss_name_t, /* desired_name */
 
const gss_OID, /* desired_mech */
 
const gss_OID, /* desired_mech */
Line 113: Line 111:
 
====gss_accept_sec_context====
 
====gss_accept_sec_context====
   
krb5_gss_accept_sec_context() has been changed such that, if the delegated credential handle parameter is non-NULL, a credential handle containing the initiator's credential for the acceptor will be always returned. (This credential handle owns a credential cache in which the service ticket to the acceptor is stored.) However, GSS_C_DELEG_FLAG will not be set unless delegation was requested by the initiator.
+
krb5_gss_accept_sec_context() has been changed such that, if the delegated credential handle parameter is non-NULL, and the verifier credential's usage is GSS_C_BOTH, a delegated credential handle will always be returned, and GSS_C_DELEG_FLAG will be set. This "proxy" credential can be passed directly to gss_init_sec_context() (for constrained delegation).
   
This credential handle can be used with gss_acquire_cred_with_cred() (below) to acquire a credentials handle for further delegation.
+
==Implementation details==
   
====gss_acquire_cred_with_cred====
+
Most of the implementation can be found in [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/s4u/src/lib/krb5/krb/s4u_creds.c src/lib/krb5/krb/s4u_creds.c].
   
<pre>
+
A new flag, KRB5_GC_NO_STORE, has been added to all the krb5_get_credentials APIs, which causes the retrieved credentials to be not stored in the credentials cache. A summary of additional flags (API compatible with Heimdal, although the actual values may differ) is below:
OM_uint32 KRB5_CALLCONV
 
gss_acquire_cred_with_cred(
 
OM_uint32 *, /* minor_status */
 
const gss_cred_id_t, /* impersonator_cred_handle */
 
const gss_cred_id_t, /* subject_cred_handle */
 
OM_uint32, /* time_req */
 
const gss_OID_set, /* desired_mechs */
 
gss_cred_usage_t, /* cred_usage */
 
gss_cred_id_t *, /* output_cred_handle */
 
gss_OID_set *, /* actual_mechs */
 
OM_uint32 *); /* time_rec */
 
</pre>
 
 
This function uses <i>impersonator_cred_handle</i> to acquire a credential for <i>subject_cred_handle</i>. Only the initiator credential usage is supported by Kerberos. The returned credential can be passed into gss_init_sec_context(). (For the Kerberos mechanism, the S4U2Proxy request is deferred until gss_init_sec_context(), because only at that point is the target name known.)
 
 
For Kerberos, <i>subject_cred_handle</i> must contain a service ticket to the impersonation principal. Absence of such a ticket will cause this call to fail. This will always be the case when using a "delegated" credentials handle returned by gss_accept_sec_context().
 
 
====gss_add_cred_with_cred====
 
   
 
<pre>
 
<pre>
OM_uint32 KRB5_CALLCONV
+
#define KRB5_GC_NO_STORE 8 /* do not store in credentials cache */
gss_add_cred_with_cred(
+
#define KRB5_GC_FORWARDABLE 16 /* acquire forwardable tickets */
OM_uint32 *, /* minor_status */
+
#define KRB5_GC_NO_TRANSIT_CHECK 32 /* disable transited check */
const gss_cred_id_t, /* impersonator_cred_handle */
+
#define KRB5_GC_CONSTRAINED_DELEGATION 64 /* constrained delegation */
gss_cred_id_t, /* input_cred_handle */
 
const gss_cred_id_t, /* subject_cred_handle */
 
const gss_OID, /* desired_mech */
 
gss_cred_usage_t, /* cred_usage */
 
OM_uint32, /* initiator_time_req */
 
OM_uint32, /* acceptor_time_req */
 
gss_cred_id_t *, /* output_cred_handle */
 
gss_OID_set *, /* actual_mechs */
 
OM_uint32 *, /* initiator_time_rec */
 
OM_uint32 *); /* acceptor_time_rec */
 
 
</pre>
 
</pre>
 
==Implementation details==
 
 
Most of the implementation can be found in [http://src.mit.edu/fisheye/browse/krb5/users/lhoward/s4u/src/lib/krb5/krb/s4u_creds.c src/lib/krb5/krb/s4u_creds.c].
 
   
 
===S4U2Self===
 
===S4U2Self===
Line 150: Line 144:
 
* acquires a TGT to the user's realm
 
* acquires a TGT to the user's realm
 
* makes the S4U2Self request, following any referrals
 
* makes the S4U2Self request, following any referrals
* stores the ticket in the credentials cache
+
* if KRB5_GC_NO_STORE is unset, stores the ticket in the credentials cache
   
 
Both variants of S4U2Self are supported.
 
Both variants of S4U2Self are supported.
 
A new flag, KRB5_GC_NO_STORE, has been added to all the krb5_get_credentials APIs, which causes the retrieved credentials to be not stored in the credentials cache.
 
   
 
The following data types are introduced into k5-int.h, along with their complementary encode/decode/free routines. Note that these types are not exposed via exported APIs.
 
The following data types are introduced into k5-int.h, along with their complementary encode/decode/free routines. Note that these types are not exposed via exported APIs.
Line 202: Line 194:
 
* checks the credentials cache for an existing ticket
 
* checks the credentials cache for an existing ticket
 
* makes the S4U2Proxy request
 
* makes the S4U2Proxy request
* stores the ticket in the credentials cache
+
* if KRB5_GC_NO_STORE is unset, stores the ticket in the credentials cache
   
A new flag, KRB5_GC_NO_STORE, has been added to all the krb5_get_credentials APIs, which causes the retrieved credentials to be not stored in the credentials cache.
+
Note: most of the logic for this is now in krb5_get_credentials(), so we could probably remove this function entirely. The one difference is that, because krb5_get_credentials() doesn't have access to the decrypted second ticket, verifying the KDC response correctly is not possible. On the other hand, GSS now uses krb5_get_credentials() because it also has no access to the decrypted second ticket (although it does have enough information to verify that the KDC supports S4U2Proxy).
   
Note: most of the logic for this is now in krb5_get_credentials(), so we could probably remove this function entirely. The one difference is that, because krb5_get_credentials() doesn't have access to the decrypted second ticket, verifying the KDC response correctly is not possible.
+
I am in favour of removing this API if we wish to remove the kvno support for S4U2Proxy.
   
 
====KDC====
 
====KDC====
Line 212: Line 204:
 
There are no changes from 1.7. Note that the backend must validate that the evidence ticket was issued by the KDC. In the Windows case, this is done by validating the KDC signature on the PAC. (The MIT KDC will reject constrained delegation requests unless the backend implements a SIGN_AUTH_DATA method.)
 
There are no changes from 1.7. Note that the backend must validate that the evidence ticket was issued by the KDC. In the Windows case, this is done by validating the KDC signature on the PAC. (The MIT KDC will reject constrained delegation requests unless the backend implements a SIGN_AUTH_DATA method.)
   
==Open issues==
+
==Future ideas==
   
* Do we actually want to store the returned S4U2Self/S4U2Proxy tickets in the credentials cache, or should we just return them as krb5_creds? Presently we do the latter (via KRB5_GC_NO_STORE).
 
* What level of abstraction do we wish to expose at the GSS-API layer?
 
 
* Do we wish to offer APIs for certificate based S4U2Self?
 
* Do we wish to offer APIs for certificate based S4U2Self?
 
* Would it be interesting/useful to offer a SAML variant of S4U2Self?
 
* Would it be interesting/useful to offer a SAML variant of S4U2Self?
Line 225: Line 215:
 
==Status==
 
==Status==
   
Implementation-wise, S4U2Self and S4U2Proxy are presently working against Windows 2008. A test program can be found in src/tests/gssapi/t_s4u.c. I have tested both a single- and two-realm (child domain) setup. Also, S4U2Self has been tested against a MIT 1.8 KDC.
+
Implementation-wise, S4U2Self and S4U2Proxy are presently working against Windows 2008. A test program can be found in src/tests/gssapi/t_s4u.c. I have tested:
  +
  +
* single-domain AD
  +
* two-domain AD (child domain)
  +
* three-domain AD (two tree roots)
  +
* MIT 1.8 KDC single-realm
  +
  +
==Review==
  +
  +
This section documents the review of the project according to [[Project policy]].
  +
It is divided into multiple sections. First, approvals should be listed. To list an approval type
  +
:<nowiki>#~~~~</nowiki>
  +
on its own line.
  +
The next section is for summarizing discussion, which should take place on krbdev@mit.edu. Provide links to the archive at http://mailman.mit.edu/pipermail/krbdev/ if appropriate. Blocking objections can be noted with <nowiki>{{project-block}}</nowiki>.
  +
  +
===Approvals===
  +
sbuckley 2009-08-24
  +
ghudson 2009-09-10
  +
  +
===Discussion===

Latest revision as of 12:40, 16 February 2010

This project was completed in release 1.8.


Working code is in the users/lhoward/s4u branch.

Contents

[edit] Background

[MS-SFU] describes two extensions to the Kerberos protocol:

  • S4U2Self, or protocol transition, which enables a service to acquire a ticket from an arbitrary principal to itself (the service is trusted to have authenticated the principal)
  • S4U2Proxy, or constrained delegation, which enables a service to use a client's ticket to itself to request another ticket for delegation

Together, these extensions are referred to as Services4User, or S4U.

The KDC will typically make some authorization checks before permitting the above: for S4U2Self, a flag on the service indicating that it is "trusted to authenticate for delegation" and, for S4U2Proxy, a set of server principals to which the service is permitted to delegate to. (Note: the trusted to authentictae for delegation flag controls whether a service can use S4U2Self to get forwardable tickets, not whether it can use S4U2Self.)

There was already some KDC-side support for these protocols in MIT Kerberos 1.7 (although supporting S4U2Proxy requires explicit backend support that is not included with the standard distribution, and S4U2Self does not support some protocol extensions Microsoft made in Windows 2008). (Note: this is old information. See ConstrainedDelegation.)

This proposal is principally concerned with the client-side (or, more correctly, service-side) implementation of S4U, although we have also updated the KDC and kadmin to more completely support S4U2Self.

[edit] Protocol extensions

[edit] S4U2Self

Readers are referred to [MS-SFU] for protocol details, but the premise behind S4U2Self is that a service requests a ticket from itself, to itself, presenting some additional preauthentication data containing the name of the user it has presumably authenticated. The KDC, after making any access checks, returns a ticket with the client-name rewritten to that in the preauthentication data. The server name is unchanged.

There are two types of PA data:

  • PA-FOR-USER, introduced in Windows 2003, which consists of the "user name" (client principal) and a checksum of the PA data with the TGT session key
  • PA_S4U_X509_USER, introduced in Windows 2008, which includes the TGS-REQ nonce to bind the S4U request to the TGS-REQ, as well as allowing the user to be identified with an X.509 certificate rather than a name.

The protocol itself is quite complicated, particularly where cross-realm authentication is concerned, so I refer the reader to [MS-SFU] for further details.

We introduce the following key usage types to krb5.h:

/* Defined in [MS-SFU] */
#define KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST  26 /* XXX note conflict with above */
#define KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY    27 /* XXX note conflict with above */

and the following PA data types (although PA-FOR-USER is present since 1.7):

#define KRB5_PADATA_FOR_USER            129 /* username protocol transition request */
#define KRB5_PADATA_S4U_X509_USER       130 /* certificate protocol transition request */

Flags for use with PA_S4U_X509_USER are also defined in k5-int.h:

#define KRB5_S4U_OPTS_CHECK_LOGON_HOURS         0400000000 /* check logon hour restrictions */
#define KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE       0x20000000 /* sign with usage 27 instead of 26 */

One important change from 1.7 is that the KDC no longer requires that the S4U2Self user principal be an enterprise principal name (UPN). KDCs that assumed this must be updated.

[edit] S4U2Proxy

Again, refer to [MS-SFU] for protocol details, but in this case the service presents a ticket (from an AP-REQ) to the KDC in the additional tickets field, whilst requesting a ticket from itself to the service to which it wishes to delegate. (A new KDC option, CNAME-IN-ADDL-TKT, is used to disambiguate this from user-to-user authentication.) The KDC, after making any access checks, returns a ticket from the additional ticket client to the delegatee.

The CNAME-IN-ADDL-TKT option is present since 1.7:

#define KDC_OPT_CNAME_IN_ADDL_TKT       0x00020000

[edit] Proposed APIs

The only public interface to Services4User is through GSS-API. We will need to export krb5 APIs for GSS to use, and possibly the kvno tool (for testing); it's probably not necessary to indirect these through an kaccess, though.

These APIs are defined in gssapi_ext.h and were designed by Nicolas Williams. Note: a mechanism need only implement gss_acquire_cred_impersonate_XXX(), as the mechglue implements gss_add_cred_impersonate_XXX() in terms of it.

There is presently no support for certificate-based protocol transition.

[edit] S4U2Self

[edit] gss_acquire_cred_impersonate_name

OM_uint32 KRB5_CALLCONV
gss_acquire_cred_impersonate_name(
    OM_uint32 *,            /* minor_status */
    const gss_cred_id_t,    /* impersonator_cred_handle */
    const gss_name_t,       /* desired_name */
    OM_uint32,              /* time_req */
    const gss_OID_set,      /* desired_mechs */
    gss_cred_usage_t,       /* cred_usage */
    gss_cred_id_t *,        /* output_cred_handle */
    gss_OID_set *,          /* actual_mechs */
    OM_uint32 *);           /* time_rec */

This function uses impersonator_cred_handle to acquire a credential for desired_name. Only the initiator credential usage is supported by Kerberos. The returned credential can be passed into gss_init_sec_context(), and is a "proxy" credential (it can be used for constrained delegation without an explicit call to gss_acquire_cred_impersonate_cred(); think of it as equivalent to a delegated credential handle returned by gss_accept_sec_context()).

[edit] gss_add_cred_impersonate_name

OM_uint32 KRB5_CALLCONV
gss_add_cred_impersonate_name(
    OM_uint32 *,            /* minor_status */
    gss_cred_id_t,          /* input_cred_handle */
    const gss_cred_id_t,    /* impersonator_cred_handle */
    const gss_name_t,       /* desired_name */
    const gss_OID,          /* desired_mech */
    gss_cred_usage_t,       /* cred_usage */
    OM_uint32,              /* initiator_time_req */
    OM_uint32,              /* acceptor_time_req */
    gss_cred_id_t *,        /* output_cred_handle */
    gss_OID_set *,          /* actual_mechs */
    OM_uint32 *,            /* initiator_time_rec */
    OM_uint32 *);           /* acceptor_time_rec */

[edit] S4U2Proxy

[edit] gss_accept_sec_context

krb5_gss_accept_sec_context() has been changed such that, if the delegated credential handle parameter is non-NULL, and the verifier credential's usage is GSS_C_BOTH, a delegated credential handle will always be returned, and GSS_C_DELEG_FLAG will be set. This "proxy" credential can be passed directly to gss_init_sec_context() (for constrained delegation).

[edit] Implementation details

Most of the implementation can be found in src/lib/krb5/krb/s4u_creds.c.

A new flag, KRB5_GC_NO_STORE, has been added to all the krb5_get_credentials APIs, which causes the retrieved credentials to be not stored in the credentials cache. A summary of additional flags (API compatible with Heimdal, although the actual values may differ) is below:

#define KRB5_GC_NO_STORE        8       /* do not store in credentials cache */
#define KRB5_GC_FORWARDABLE             16  /* acquire forwardable tickets */
#define KRB5_GC_NO_TRANSIT_CHECK        32  /* disable transited check */
#define KRB5_GC_CONSTRAINED_DELEGATION  64  /* constrained delegation */

[edit] S4U2Self

[edit] API

krb5_error_code KRB5_CALLCONV
krb5_get_credentials_for_user(krb5_context context, krb5_flags options,
                              krb5_ccache ccache, krb5_creds *in_creds,
                              krb5_data *subject_cert,
                              krb5_creds **out_creds)

krb5_get_credentials_for_user() does the following:

  • checks the credentials cache for an existing ticket
  • identifies the user's realm using an AS-REQ, if a certificate or enterprise principal name is being used
  • acquires a TGT to the user's realm
  • makes the S4U2Self request, following any referrals
  • if KRB5_GC_NO_STORE is unset, stores the ticket in the credentials cache

Both variants of S4U2Self are supported.

The following data types are introduced into k5-int.h, along with their complementary encode/decode/free routines. Note that these types are not exposed via exported APIs.

typedef struct _krb5_pa_for_user {
    krb5_principal      user;
    krb5_checksum       cksum;
    krb5_data           auth_package;
} krb5_pa_for_user;

typedef struct _krb5_s4u_userid {
    krb5_int32          nonce;
    krb5_principal      user;
    krb5_data           subject_cert;
    krb5_flags          options;
} krb5_s4u_userid;

typedef struct _krb5_pa_s4u_x509_user {
    krb5_s4u_userid     user_id;
    krb5_checksum       cksum;
} krb5_pa_s4u_x509_user;

[edit] KDC

  • S4U2Self client names are no longer required to be an enterprise principal name, as they were in 1.7
  • the Windows 2008 variant of S4U2Self is supported
  • kadmin has been updated to support the ok_to_auth_as_delegate (and, for completeness) no_auth_data_required attributes. Services with ok_to_auth_as_delegate are allowed to use S4U2Self

[edit] S4U2Proxy

[edit] API

krb5_error_code KRB5_CALLCONV
krb5_get_credentials_for_proxy(krb5_context context,
                               krb5_flags options,
                               krb5_ccache ccache,
                               krb5_creds *in_creds,
                               krb5_ticket *evidence_tkt,
                               krb5_creds **out_creds)

krb5_get_credentials_for_proxy() does the following:

  • checks the credentials cache for an existing ticket
  • makes the S4U2Proxy request
  • if KRB5_GC_NO_STORE is unset, stores the ticket in the credentials cache

Note: most of the logic for this is now in krb5_get_credentials(), so we could probably remove this function entirely. The one difference is that, because krb5_get_credentials() doesn't have access to the decrypted second ticket, verifying the KDC response correctly is not possible. On the other hand, GSS now uses krb5_get_credentials() because it also has no access to the decrypted second ticket (although it does have enough information to verify that the KDC supports S4U2Proxy).

I am in favour of removing this API if we wish to remove the kvno support for S4U2Proxy.

[edit] KDC

There are no changes from 1.7. Note that the backend must validate that the evidence ticket was issued by the KDC. In the Windows case, this is done by validating the KDC signature on the PAC. (The MIT KDC will reject constrained delegation requests unless the backend implements a SIGN_AUTH_DATA method.)

[edit] Future ideas

  • Do we wish to offer APIs for certificate based S4U2Self?
  • Would it be interesting/useful to offer a SAML variant of S4U2Self?

[edit] Tools

The kvno utility has been updated to support the -U user option (for S4U2Self) and the -P option (for S4U2Proxy, which changes the meaning of the additional service arguments to be delegatees).

[edit] Status

Implementation-wise, S4U2Self and S4U2Proxy are presently working against Windows 2008. A test program can be found in src/tests/gssapi/t_s4u.c. I have tested:

  • single-domain AD
  • two-domain AD (child domain)
  • three-domain AD (two tree roots)
  • MIT 1.8 KDC single-realm

[edit] Review

This section documents the review of the project according to Project policy. It is divided into multiple sections. First, approvals should be listed. To list an approval type

#~~~~

on its own line. The next section is for summarizing discussion, which should take place on krbdev@mit.edu. Provide links to the archive at http://mailman.mit.edu/pipermail/krbdev/ if appropriate. Blocking objections can be noted with {{project-block}}.

[edit] Approvals

sbuckley 2009-08-24 ghudson 2009-09-10

[edit] Discussion

Personal tools