Hi,

this is the last patch in the series to add the basic support for AD as
a server. With this patch the kerberos backend will use the user
principal name provided by the server to get the TGT. To make the client
side kerberos libraries happy the realm part is always made upper case.

bye,
Sumit
>From 6bc7402f112d8ed612d0a8128e74459d4c072809 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 21 Aug 2009 12:08:31 +0200
Subject: [PATCH] use stored upn if available

If a user principle name (upn) can be found in sysdb the krb5
backend will use this otherwise is build as usern...@realm. It is
checked that the realm is upper case only.
---
 server/providers/krb5/krb5_auth.c |  121 +++++++++++++++++++++++++++++++------
 1 files changed, 101 insertions(+), 20 deletions(-)

diff --git a/server/providers/krb5/krb5_auth.c 
b/server/providers/krb5/krb5_auth.c
index ffbfd7b..45bbe4c 100644
--- a/server/providers/krb5/krb5_auth.c
+++ b/server/providers/krb5/krb5_auth.c
@@ -31,6 +31,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <pwd.h>
+#include <ctype.h>
 
 #include <security/pam_modules.h>
 
@@ -40,6 +41,25 @@
 #include "krb5_plugin/sssd_krb5_locator_plugin.h"
 #include "providers/krb5/krb5_auth.h"
 
+#define REALM_SEPARATOR '@'
+
+static void make_realm_upper_case(const char *upn)
+{
+    char *c;
+
+    c = strchr(upn, REALM_SEPARATOR);
+    if (c == NULL) {
+        DEBUG(9, ("No realm delimiter found in upn [%s].\n", upn));
+        return;
+    }
+
+    while(*(++c) != '\0') {
+        c[0] = toupper(*c);
+    }
+
+    return;
+}
+
 static void fd_nonblocking(int fd) {
     int flags;
 
@@ -77,13 +97,13 @@ static void krb5_cleanup(struct krb5_req *kr)
     talloc_free(kr);
 }
 
-static int krb5_setup(struct be_req *req, struct krb5_req **krb5_req)
+static int krb5_setup(struct be_req *req, const char *user_princ_str,
+                      struct krb5_req **krb5_req)
 {
     struct krb5_req *kr = NULL;
     struct krb5_ctx *krb5_ctx;
     struct pam_data *pd;
     krb5_error_code kerr = 0;
-    char *user_princ_str = NULL;
 
     pd = talloc_get_type(req->req_data, struct pam_data);
 
@@ -105,18 +125,6 @@ static int krb5_setup(struct be_req *req, struct krb5_req 
**krb5_req)
         goto failed;
     }
 
-/* TODO: try to read user principal from id backend, use user + realm as a
-   fallback */
-    if (kr->pd->user != NULL && krb5_ctx->realm != NULL) {
-        user_princ_str = talloc_asprintf(kr, "%...@%s", kr->pd->user,
-                                                      krb5_ctx->realm);
-    }
-    if (user_princ_str == NULL) {
-        DEBUG(1, ("talloc_asprintf failed.\n"));
-        kerr = ENOMEM;
-        goto failed;
-    }
-
     kerr = krb5_parse_name(kr->ctx, user_princ_str, &kr->princ);
     if (kerr != 0) {
         KRB5_DEBUG(1, kerr);
@@ -374,16 +382,16 @@ static ssize_t tgt_req_recv(struct tevent_req *req, 
TALLOC_CTX *mem_ctx,
     return state->len;
 }
 
+static void get_user_upn_done(void *pvt, int err, struct ldb_result *res);
 static void krb5_pam_handler_done(struct tevent_req *req);
 static void krb5_pam_handler_cache_done(struct tevent_req *treq);
 
 static void krb5_pam_handler(struct be_req *be_req)
 {
-    struct krb5_req *kr = NULL;
-    struct tevent_req *req;
     int ret;
     struct pam_data *pd;
     int pam_status=PAM_SYSTEM_ERR;
+    const char **attrs;
 
     pd = talloc_get_type(be_req->req_data, struct pam_data);
 
@@ -393,22 +401,95 @@ static void krb5_pam_handler(struct be_req *be_req)
         goto done;
     }
 
-    ret = krb5_setup(be_req, &kr);
+    attrs = talloc_array(be_req, const char *, 2);
+    if (attrs == NULL) {
+        goto done;
+    }
+
+    attrs[0] = SYSDB_UPN;
+    attrs[1] = NULL;
+
+    ret = sysdb_get_user_attr(be_req, be_req->be_ctx->sysdb,
+                              be_req->be_ctx->domain, pd->user, attrs,
+                              get_user_upn_done, be_req);
+
+    if (ret) {
+        goto done;
+    }
+
+    return;
+
+done:
+    pd->pam_status = pam_status;
+
+    be_req->fn(be_req, pam_status, NULL);
+}
+
+static void get_user_upn_done(void *pvt, int err, struct ldb_result *res)
+{
+    struct be_req *be_req = talloc_get_type(pvt, struct be_req);
+    struct krb5_ctx *krb5_ctx;
+    struct krb5_req *kr = NULL;
+    struct tevent_req *req;
+    int ret;
+    struct pam_data *pd;
+    int pam_status=PAM_SYSTEM_ERR;
+    const char *upn = NULL;
+
+    pd = talloc_get_type(be_req->req_data, struct pam_data);
+    krb5_ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_AUTH].pvt_bet_data,
+                               struct krb5_ctx);
+
+    if (err != LDB_SUCCESS) {
+        DEBUG(5, ("sysdb search for upn of user [%s] failed.\n", pd->user));
+        goto failed;
+    }
+
+    switch (res->count) {
+    case 0:
+        DEBUG(5, ("No upn for user [%s] found.\n", pd->user));
+        break;
+
+    case 1:
+        upn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_UPN, NULL);
+        if (upn == NULL) {
+            /* NOTE: this is a hack, works only in some environments */
+            if (krb5_ctx->realm != NULL) {
+                upn = talloc_asprintf(be_req, "%...@%s", pd->user,
+                                      krb5_ctx->realm);
+            }
+        }
+        break;
+
+    default:
+        DEBUG(1, ("A user search by name (%s) returned > 1 results!\n",
+                  pd->user));
+        break;
+    }
+
+    if (upn == NULL) {
+        DEBUG(1, ("Cannot set UPN.\n"));
+        goto failed;
+    }
+
+    make_realm_upper_case(upn);
+
+    ret = krb5_setup(be_req, upn, &kr);
     if (ret != EOK) {
         DEBUG(1, ("krb5_setup failed.\n"));
-        goto done;
+        goto failed;
     }
 
     req = tgt_req_send(be_req, be_req->be_ctx->ev, kr);
     if (req == NULL) {
         DEBUG(1, ("tgt_req_send failed.\n"));
-        goto done;
+        goto failed;
     }
 
     tevent_req_set_callback(req, krb5_pam_handler_done, kr);
     return;
 
-done:
+failed:
     krb5_cleanup(kr);
 
     pd->pam_status = pam_status;
-- 
1.6.2.5

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to