Add check_policy_as and check_policy_tgs to the DAL table with
authorGreg Hudson <ghudson@mit.edu>
Tue, 13 Jul 2010 00:53:46 +0000 (00:53 +0000)
committerGreg Hudson <ghudson@mit.edu>
Tue, 13 Jul 2010 00:53:46 +0000 (00:53 +0000)
corresponding libkdb5 APIs, replacing the CHECK_POLICY_AS and
CHECK_POLICY_TGS methods of db_invoke.

ticket: 6749
status: open

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24184 dc483132-0cff-0310-8789-dd5450dbe970

14 files changed:
src/include/kdb.h
src/kdc/kdc_util.c
src/kdc/policy.c
src/lib/kdb/kdb5.c
src/lib/kdb/libkdb5.exports
src/plugins/kdb/db2/db2_exp.c
src/plugins/kdb/db2/kdb_db2.c
src/plugins/kdb/db2/kdb_db2.h
src/plugins/kdb/db2/kdb_ext.c
src/plugins/kdb/ldap/ldap_exp.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ext.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports

index cb9a32820cd8f1b80d0fa631014ae73311b0df03..53a4e24e7a16df5834edd1da0d21c9c357678e73 100644 (file)
@@ -323,40 +323,11 @@ extern char *krb5_mkey_pwd_prompt2;
 #define KRB5_DB_LOCKMODE_PERMANENT    0x0008
 
 /* db_invoke methods */
-#define KRB5_KDB_METHOD_CHECK_POLICY_AS                 0x00000030
-#define KRB5_KDB_METHOD_CHECK_POLICY_TGS                0x00000040
 #define KRB5_KDB_METHOD_AUDIT_AS                        0x00000050
 #define KRB5_KDB_METHOD_AUDIT_TGS                       0x00000060
 #define KRB5_KDB_METHOD_REFRESH_POLICY                  0x00000070
 #define KRB5_KDB_METHOD_CHECK_ALLOWED_TO_DELEGATE       0x00000080
 
-typedef struct _kdb_check_policy_as_req {
-    krb5_magic magic;
-    krb5_kdc_req *request;
-    krb5_db_entry *client;
-    krb5_db_entry *server;
-    krb5_timestamp kdc_time;
-} kdb_check_policy_as_req;
-
-typedef struct _kdb_check_policy_as_rep {
-    krb5_magic magic;
-    const char *status;
-    krb5_data e_data;
-} kdb_check_policy_as_rep;
-
-typedef struct _kdb_check_policy_tgs_req {
-    krb5_magic magic;
-    krb5_kdc_req *request;
-    krb5_db_entry *server;
-    krb5_ticket *ticket;
-} kdb_check_policy_tgs_req;
-
-typedef struct _kdb_check_policy_tgs_rep {
-    krb5_magic magic;
-    const char *status;
-    krb5_data e_data;
-} kdb_check_policy_tgs_rep;
-
 typedef struct _kdb_audit_as_req {
     krb5_magic magic;
     krb5_kdc_req *request;
@@ -649,6 +620,21 @@ krb5_error_code krb5_db_check_transited_realms(krb5_context kcontext,
                                                const krb5_data *client_realm,
                                                const krb5_data *server_realm);
 
+krb5_error_code krb5_db_check_policy_as(krb5_context kcontext,
+                                        krb5_kdc_req *request,
+                                        krb5_db_entry *client,
+                                        krb5_db_entry *server,
+                                        krb5_timestamp kdc_time,
+                                        const char **status,
+                                        krb5_data *e_data);
+
+krb5_error_code krb5_db_check_policy_tgs(krb5_context kcontext,
+                                         krb5_kdc_req *request,
+                                         krb5_db_entry *server,
+                                         krb5_ticket *ticket,
+                                         const char **status,
+                                         krb5_data *e_data);
+
 krb5_error_code krb5_db_invoke ( krb5_context kcontext,
                                  unsigned int method,
                                  const krb5_data *req,
@@ -1262,25 +1248,45 @@ typedef struct _kdb_vftabl {
                                               const krb5_data *client_realm,
                                               const krb5_data *server_realm);
 
+    /*
+     * Optional: Perform a policy check on an AS request, in addition to the
+     * standard policy checks.  Return 0 if the AS request is allowed.  If the
+     * AS request is not allowed:
+     *   - Place a short string literal into *status.
+     *   - If desired, place data into e_data.  Any data placed here will be
+     *     freed by the caller using the standard free function.
+     *   - Return an appropriate error (such as KDC_ERR_POLICY).
+     */
+    krb5_error_code (*check_policy_as)(krb5_context kcontext,
+                                       krb5_kdc_req *request,
+                                       krb5_db_entry *client,
+                                       krb5_db_entry *server,
+                                       krb5_timestamp kdc_time,
+                                       const char **status,
+                                       krb5_data *e_data);
+
+    /*
+     * Optional: Perform a policy check on a TGS request, in addition to the
+     * standard policy checks.  Return 0 if the TGS request is allowed.  If the
+     * TGS request is not allowed:
+     *   - Place a short string literal into *status.
+     *   - If desired, place data into e_data.  Any data placed here will be
+     *     freed by the caller using the standard free function.
+     *   - Return an appropriate error (such as KDC_ERR_POLICY).
+     * The input parameter ticket contains the TGT used in the TGS request.
+     */
+    krb5_error_code (*check_policy_tgs)(krb5_context kcontext,
+                                        krb5_kdc_req *request,
+                                        krb5_db_entry *server,
+                                        krb5_ticket *ticket,
+                                        const char **status,
+                                        krb5_data *e_data);
+
     /*
      * Optional: Perform an operation on input data req with output stored in
      * rep.  Return KRB5_PLUGIN_OP_NOTSUPP if the module does not implement the
      * method.  Defined methods are:
      *
-     * KRB5_KDB_METHOD_CHECK_POLICY_AS: req contains a kdb_check_policy_as_req
-     *     structure.  Perform a policy check on an AS request, in addition to
-     *     the standard policy checks.  Return 0 if the AS request is allowed
-     *     or an appropriate error (such as KDC_ERR_POLICY) if it is
-     *     disallowed.  Place in rep a kdb_check_policy_as_rep structure
-     *     containing a status string and e_data value to return to the client
-     *     if the policy check fails.  The status string may be NULL, but must
-     *     not contain allocated data as it will not be freed.  The e_data
-     *     structure may be empty; if not, it will be freed by the caller using
-     *     the standard free function.
-     *
-     * KRB5_KDB_METHOD_CHECK_POLICY_TGS: Same as above, except the structures
-     *     are kdb_check_policy_tgs_req and kdb_check_policy_tgs_rep.
-     *
      * KRB5_KDB_METHOD_AUDIT_AS: req contains a kdb_audit_as_req structure.
      *     Informs the module of a successful or unsuccessful AS request.  Do
      *     not place any data in rep.
index db5434d52b03e5e2477e52835b6b83ab81af1169..b892a2748579835b729ff103cd97c8c51d6a7b53 100644 (file)
@@ -1051,9 +1051,13 @@ validate_as_request(register krb5_kdc_req *request, krb5_db_entry client,
         return(KDC_ERR_MUST_USE_USER2USER);
     }
 
-    /*
-     * Check against local policy
-     */
+    /* Perform KDB module policy checks. */
+    errcode = krb5_db_check_policy_as(kdc_context, request, &client, &server,
+                                      kdc_time, status, e_data);
+    if (errcode && errcode != KRB5_PLUGIN_OP_NOTSUPP)
+        return errcode;
+
+    /* Check against local policy. */
     errcode = against_local_policy_as(request, client, server,
                                       kdc_time, status, e_data);
     if (errcode)
@@ -1468,9 +1472,13 @@ validate_tgs_request(register krb5_kdc_req *request, krb5_db_entry server,
         return KRB_ERR_GENERIC;
     }
 
-    /*
-     * Check local policy
-     */
+    /* Perform KDB module policy checks. */
+    errcode = krb5_db_check_policy_tgs(kdc_context, request, &server,
+                                       ticket, status, e_data);
+    if (errcode && errcode != KRB5_PLUGIN_OP_NOTSUPP)
+        return errcode;
+
+    /* Check local policy. */
     errcode = against_local_policy_tgs(request, server, ticket,
                                        status, e_data);
     if (errcode)
index fa403e58c6235a05b1c8fdf158f27a3e1e5ee7fe..939ddb06afbefe609d856e81fe42379c5c06f8fd 100644 (file)
@@ -63,12 +63,6 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
                         krb5_db_entry server, krb5_timestamp kdc_time,
                         const char **status, krb5_data *e_data)
 {
-    krb5_error_code             code;
-    kdb_check_policy_as_req     req;
-    kdb_check_policy_as_rep     rep;
-    krb5_data                   req_data;
-    krb5_data                   rep_data;
-
 #if 0
     /* An AS request must include the addresses field */
     if (request->addresses == 0) {
@@ -77,37 +71,7 @@ against_local_policy_as(register krb5_kdc_req *request, krb5_db_entry client,
     }
 #endif
 
-    memset(&req, 0, sizeof(req));
-    memset(&rep, 0, sizeof(rep));
-
-    req.request                 = request;
-    req.client                  = &client;
-    req.server                  = &server;
-    req.kdc_time                = kdc_time;
-
-    req_data.data = (void *)&req;
-    req_data.length = sizeof(req);
-
-    rep_data.data = (void *)&rep;
-    rep_data.length = sizeof(rep);
-
-    code = krb5_db_invoke(kdc_context,
-                          KRB5_KDB_METHOD_CHECK_POLICY_AS,
-                          &req_data,
-                          &rep_data);
-    if (code == KRB5_PLUGIN_OP_NOTSUPP)
-        return 0;
-
-    *status = rep.status;
-    *e_data = rep.e_data;
-
-    if (code != 0) {
-        code -= ERROR_TABLE_BASE_krb5;
-        if (code < 0 || code > 128)
-            code = KRB_ERR_GENERIC;
-    }
-
-    return code;
+    return 0;                   /* not against policy */
 }
 
 /*
@@ -118,12 +82,6 @@ against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
                          krb5_ticket *ticket, const char **status,
                          krb5_data *e_data)
 {
-    krb5_error_code             code;
-    kdb_check_policy_tgs_req    req;
-    kdb_check_policy_tgs_rep    rep;
-    krb5_data                   req_data;
-    krb5_data                   rep_data;
-
 #if 0
     /*
      * For example, if your site wants to disallow ticket forwarding,
@@ -136,34 +94,5 @@ against_local_policy_tgs(register krb5_kdc_req *request, krb5_db_entry server,
     }
 #endif
 
-    memset(&req, 0, sizeof(req));
-    memset(&rep, 0, sizeof(rep));
-
-    req.request                 = request;
-    req.server                  = &server;
-    req.ticket                  = ticket;
-
-    req_data.data = (void *)&req;
-    req_data.length = sizeof(req);
-
-    rep_data.data = (void *)&rep;
-    rep_data.length = sizeof(rep);
-
-    code = krb5_db_invoke(kdc_context,
-                          KRB5_KDB_METHOD_CHECK_POLICY_TGS,
-                          &req_data,
-                          &rep_data);
-    if (code == KRB5_PLUGIN_OP_NOTSUPP)
-        return 0;
-
-    *status = rep.status;
-    *e_data = rep.e_data;
-
-    if (code != 0) {
-        code -= ERROR_TABLE_BASE_krb5;
-        if (code < 0 || code > 128)
-            code = KRB_ERR_GENERIC;
-    }
-
-    return code;
+    return 0;                           /* not against policy */
 }
index 0e12eb183f02ced6f55b614400af34f380bd8645..521bbb40b380ece9448302830fd74c7cc4d9c430 100644 (file)
@@ -2264,6 +2264,45 @@ krb5_db_check_transited_realms(krb5_context kcontext,
                                      server_realm);
 }
 
+krb5_error_code
+krb5_db_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
+                        krb5_db_entry *client, krb5_db_entry *server,
+                        krb5_timestamp kdc_time, const char **status,
+                        krb5_data *e_data)
+{
+    krb5_error_code ret;
+    kdb_vftabl *v;
+
+    *status = NULL;
+    *e_data = empty_data();
+    ret = get_vftabl(kcontext, &v);
+    if (ret)
+        return ret;
+    if (v->check_policy_as == NULL)
+        return KRB5_PLUGIN_OP_NOTSUPP;
+    return v->check_policy_as(kcontext, request, client, server, kdc_time,
+                              status, e_data);
+}
+
+krb5_error_code
+krb5_db_check_policy_tgs(krb5_context kcontext, krb5_kdc_req *request,
+                         krb5_db_entry *server, krb5_ticket *ticket,
+                         const char **status, krb5_data *e_data)
+{
+    krb5_error_code ret;
+    kdb_vftabl *v;
+
+    *status = NULL;
+    *e_data = empty_data();
+    ret = get_vftabl(kcontext, &v);
+    if (ret)
+        return ret;
+    if (v->check_policy_tgs == NULL)
+        return KRB5_PLUGIN_OP_NOTSUPP;
+    return v->check_policy_tgs(kcontext, request, server, ticket, status,
+                               e_data);
+}
+
 krb5_error_code
 krb5_db_invoke(krb5_context kcontext,
                unsigned int method,
index dcba09e937600046739c815b7bd8b9c74aa30d0b..f83532d15f00da1db95ef22f558964dee952e97b 100644 (file)
@@ -3,6 +3,8 @@ krb5_db_open
 krb5_db_inited
 krb5_db_alloc
 krb5_db_free
+krb5_db_check_policy_as
+krb5_db_check_policy_tgs
 krb5_db_check_transited_realms
 krb5_db_create
 krb5_db_delete_principal
index c2748861fb34f0dafa74713dc8f345a5ea474a12..a95d47dfcb86847816db469c0471bd3957cf25b2 100644 (file)
@@ -180,6 +180,12 @@ WRAP_K (krb5_db2_promote_db,
         ( krb5_context kcontext, char *conf_section, char **db_args ),
         (kcontext, conf_section, db_args));
 
+WRAP_K (krb5_db2_check_policy_as,
+        (krb5_context kcontext, krb5_kdc_req *request, krb5_db_entry *client,
+         krb5_db_entry *server, krb5_timestamp kdc_time, const char **status,
+         krb5_data *e_data),
+        (kcontext, request, client, server, kdc_time, status, e_data));
+
 WRAP_K (krb5_db2_invoke,
         (krb5_context kcontext,
          unsigned int method,
@@ -243,5 +249,7 @@ kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_db2, kdb_function_table) = {
     /* blah blah blah */ 0,0,0,0,0,
     /* promote_db */                    wrap_krb5_db2_promote_db,
     0, 0, 0, 0,
+    /* check_policy_as */               wrap_krb5_db2_check_policy_as,
+    0,
     /* invoke */                        wrap_krb5_db2_invoke
 };
index 707bf842b6413f105d726f120c0793514f169bf5..a53e26258a1f0246677c20543096ae206f625930 100644 (file)
@@ -1635,3 +1635,17 @@ errout:
 
     return retval;
 }
+
+krb5_error_code
+krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
+                         krb5_db_entry *client, krb5_db_entry *server,
+                         krb5_timestamp kdc_time, const char **status,
+                         krb5_data *e_data)
+{
+    krb5_error_code retval;
+
+    retval = krb5_db2_lockout_check_policy(kcontext, client, kdc_time);
+    if (retval == KRB5KDC_ERR_CLIENT_REVOKED)
+        *status = "LOCKED_OUT";
+    return retval;
+}
index 6096dc4b1bb4f8e4349ff659b45a99766369dd55..0bddcf4a59b9002087c5b3764e33acca0efdbb98 100644 (file)
@@ -146,6 +146,12 @@ krb5_db2_lockout_audit(krb5_context context,
                        krb5_timestamp stamp,
                        krb5_error_code status);
 
+krb5_error_code
+krb5_db2_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
+                         krb5_db_entry *client, krb5_db_entry *server,
+                         krb5_timestamp kdc_time, const char **status,
+                         krb5_data *e_data);
+
 /* methods */
 krb5_error_code
 krb5_db2_invoke(krb5_context context,
index 1895b70e4a6288d66be3f2b6eb8d0a107eb11db6..8f7ad942788c02e996c1da345340520346a8cfc3 100644 (file)
 #include <errno.h>
 #include "kdb_db2.h"
 
-static krb5_error_code
-krb5_db2_check_policy_as(krb5_context context,
-                         unsigned int method,
-                         const krb5_data *request,
-                         krb5_data *response)
-{
-    const kdb_check_policy_as_req *req;
-    kdb_check_policy_as_rep *rep;
-    krb5_error_code code;
-
-    req = (const kdb_check_policy_as_req *)request->data;
-    rep = (kdb_check_policy_as_rep *)response->data;
-
-    rep->status = NULL;
-
-    code = krb5_db2_lockout_check_policy(context, req->client,
-                                         req->kdc_time);
-    if (code == KRB5KDC_ERR_CLIENT_REVOKED)
-        rep->status = "LOCKED_OUT";
-
-    return code;
-}
-
 static krb5_error_code
 krb5_db2_audit_as(krb5_context context,
                   unsigned int method,
@@ -83,9 +60,6 @@ krb5_db2_invoke(krb5_context context,
     krb5_error_code code = KRB5_PLUGIN_OP_NOTSUPP;
 
     switch (method) {
-    case KRB5_KDB_METHOD_CHECK_POLICY_AS:
-        code = krb5_db2_check_policy_as(context, method, req, rep);
-        break;
     case KRB5_KDB_METHOD_AUDIT_AS:
         code = krb5_db2_audit_as(context, method, req, rep);
         break;
index 3228aa06ef25d04dced6a052ad43f58e2222b229..8236406c2f6f4ef81252afde887c46022fa365c7 100644 (file)
@@ -84,6 +84,8 @@ kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_ldap, kdb_function_table) = {
     /* encrypt_key_data */                  NULL,
     /* sign_authdata */                     NULL,
     /* check_transited_realms */            NULL,
+    /* check_policy_as */                   krb5_ldap_check_policy_as,
+    /* check_policy_tgs */                  NULL,
     /* invoke */                            krb5_ldap_invoke,
 
 };
index fdbb1a17a33c07e98354f91a1af135ae332b6ea8..0330e15e8afcedc1ceff05bc2f9e3fadf2a038f9 100644 (file)
 #include <errno.h>
 #include "kdb_ldap.h"
 
-static krb5_error_code
-krb5_ldap_check_policy_as(krb5_context context,
-                          unsigned int method,
-                          const krb5_data *request,
-                          krb5_data *response)
-{
-    const kdb_check_policy_as_req *req;
-    kdb_check_policy_as_rep *rep;
-    krb5_error_code code;
-
-    req = (const kdb_check_policy_as_req *)request->data;
-    rep = (kdb_check_policy_as_rep *)response->data;
-
-    rep->status = NULL;
-
-    code = krb5_ldap_lockout_check_policy(context, req->client,
-                                          req->kdc_time);
-    if (code == KRB5KDC_ERR_CLIENT_REVOKED)
-        rep->status = "LOCKED_OUT";
-
-    return code;
-}
-
 static krb5_error_code
 krb5_ldap_audit_as(krb5_context context,
                    unsigned int method,
@@ -117,9 +94,6 @@ krb5_ldap_invoke(krb5_context context,
     krb5_error_code code = KRB5_PLUGIN_OP_NOTSUPP;
 
     switch (method) {
-    case KRB5_KDB_METHOD_CHECK_POLICY_AS:
-        code = krb5_ldap_check_policy_as(context, method, req, rep);
-        break;
     case KRB5_KDB_METHOD_AUDIT_AS:
         code = krb5_ldap_audit_as(context, method, req, rep);
         break;
index 633de85d23a36c015d19bb9d88eaa141a728b0fa..7127ce4a03122961d8226283ddef954f1b6229a8 100644 (file)
@@ -527,3 +527,17 @@ kldap_ensure_initialized(void)
 {
     return CALL_INIT_FUNCTION (kldap_init_fn);
 }
+
+krb5_error_code
+krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
+                          krb5_db_entry *client, krb5_db_entry *server,
+                          krb5_timestamp kdc_time, const char **status,
+                          krb5_data *e_data)
+{
+    krb5_error_code retval;
+
+    retval = krb5_ldap_lockout_check_policy(kcontext, client, kdc_time);
+    if (retval == KRB5KDC_ERR_CLIENT_REVOKED)
+        *status = "LOCKED_OUT";
+    return retval;
+}
index 35dd12e02946767686fe6653487db7418a385198..8e935e193785d49f47276c5133806e68ed31d8f7 100644 (file)
@@ -296,6 +296,11 @@ has_modify_increment(krb5_context, char *);
 krb5_error_code
 krb5_ldap_free_server_context_params(krb5_ldap_context *ldap_context);
 
+krb5_error_code
+krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
+                          krb5_db_entry *client, krb5_db_entry *server,
+                          krb5_timestamp kdc_time, const char **status,
+                          krb5_data *e_data);
 
 /* DAL functions */
 
index 7f285ce94139de974393d5789c361ad72da7934e..affdb38bb921557870d80114397a7ba5fdc5a09b 100644 (file)
@@ -44,4 +44,5 @@ krb5_ldap_unlock
 krb5_ldap_create
 krb5_ldap_set_mkey_list
 krb5_ldap_get_mkey_list
+krb5_ldap_check_policy_as
 krb5_ldap_invoke