logo_kerberos.gif

Projects/Services4User

From K5Wiki
< Projects(Difference between revisions)
Jump to: navigation, search
(Status)
 
(47 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.
+
{{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 14: Line 12:
 
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 it would be interesting to update the KDC to address the limitations mentioned above.
+
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.
   
 
==Protocol extensions==
 
==Protocol extensions==
Line 46: Line 44:
 
</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 67: Line 65:
 
==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.
   
===gss_krb5_create_sec_context_for_principal()===
+
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.
   
<pre>
+
There is presently no support for certificate-based protocol transition.
OM_uint32
 
gss_krb5_create_sec_context_for_principal(OM_uint32 *minor_status,
 
gss_ctx_id_t *context_handle,
 
gss_cred_id_t verifier_cred_handle,
 
gss_name_t principal,
 
OM_uint32 req_flags,
 
OM_uint32 time_req,
 
gss_name_t *src_name,
 
gss_OID *mech_type,
 
OM_uint32 *ret_flags,
 
OM_uint32 *time_ret,
 
gss_cred_id_t *delegated_cred_handle);
 
</pre>
 
   
gss_krb5_create_sec_context_for_principal() synthesises an acceptor-side security context for an arbitrary principal. (There's probably a better name for this. The word "impersonate" seems good, but it has a different meaning on Windows, which could be confusing.)
+
===S4U2Self===
   
verifier_cred_handle must be both an initiator- and acceptor-side credentials handle, because a TGT is required to perform S4U2Self.
+
====gss_acquire_cred_impersonate_name====
   
Essentially this function acquires Kerberos credentials using S4U2Self, wraps them up as GSS credentials, and then calls gss_init_sec_context() and gss_accept_sec_context(). This provides a simple interface for developers, at the expense perhaps of some transparency. I do suspect that if we provide complex APIs they won't be used, or giant slabs of sample code will be copied and pasted.
+
<pre>
  +
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 */
  +
</pre>
   
That said, alternatives to this API are:
+
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()).
   
* one which returns a GSS initiator credential (gss_krb5_acquire_creds_for_principal())
+
====gss_add_cred_impersonate_name====
* one which returns a GSS initial context token (gss_init_sec_context_for_principal())
 
   
The current API has no provision for certificate-based protocol transition.
+
<pre>
  +
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 */
  +
</pre>
   
===gss_krb5_add_sec_context_delegatee()===
+
===S4U2Proxy===
   
gss_krb5_add_sec_context_delegatee() creates or updates a skeletal context that can be passed to gss_accept_sec_context(), such that
+
====gss_accept_sec_context====
delegated_cred_handle will contain credentials for delegating to the specified principals. The existing GSS-API delegation model is maintained; the
 
only difference being that the delegated credentials handle contains a set of service tickets, instead of a TGT.
 
   
This takes advantage of the new behaviour of gss_accept_sec_context() introduced in 1.7 (although there was a bug in that implementation), where gss_set_sec_context_option() can be used to create a context with some parameters which is passed to gss_accept_sec_context() with the initial context token. Prior to that, the context handle on the first call to gss_accept_sec_context() was always GSS_C_NO_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).
 
Some changes were required to gss_accept_sec_context() and gss_init_sec_context() to accept and validate these skeletal contexts. (Note that such a context should never be passed to gss_init_sec_context().)
 
   
 
==Implementation details==
 
==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].
 
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].
  +
  +
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:
  +
  +
<pre>
  +
#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 */
  +
</pre>
   
 
===S4U2Self===
 
===S4U2Self===
Line 113: Line 120:
 
* 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, but the Windows 2008 version is currently disabled pending some interoperability debugging.
+
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.
 
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 163: Line 170:
 
* 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
  +
  +
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.
   
 
====KDC====
 
====KDC====
Line 169: Line 176:
 
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? The credentials cache could fill up rapidly on a busy server.
 
* Do we want to update our KDC to handle the Window 2008 variant of S4U2Self? (Update: done, but untested)
 
* Do we want to implement sample code to handle S4U2Proxy in our KDC? Note that, without Windows authorization data, this requires additional authorization data (which Heimdal appears to support) to avoid a service forging an evidence ticket
 
* 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 184: Line 187:
 
==Status==
 
==Status==
   
Implementation-wise, S4U2Self (Windows 2003) 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.
+
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>.
   
Remaining work:
+
===Approvals===
  +
sbuckley 2009-08-24
  +
ghudson 2009-09-10
   
* Review of design and API
+
===Discussion===
* Debug why S4U2Self fails with Windows 2008 protocol variant
 
* Test against MIT KDC
 

Latest revision as of 13: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