[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Freeipa-devel] [PATCHES] reorg of code continued



Three patches to improve our internal interfaces.

Create a second authenticator module interface, so that identity and
authenticator modules are 2 different things.

Load the authenticator module per domain based on configuration in the
domain config entry.

Initial changes to the pam responder to cope with the changes

Move the name parsing routines into the common responder code, and move
pcre initialization into sss_process_init() with data hanging on the
responder context, also add a config/names section where to configure
name parsing rules.

All is tested and seem to work as it should, I've also added more
configuration samples for the pam proxy stuff (tested with sudo and that
one works so far ie pam->pam_sss->sssd_pam->proxy->pam_unix/pam_ldap).

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York
>From ca62790ec85ec4c19b34fa6816cfe3e3779f7e43 Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce redhat com>
Date: Sat, 4 Apr 2009 12:21:18 -0400
Subject: [PATCH] Split modules types in Identity and Authenticator

The same module may implement both types, but initializatrion will be
nonetheless performed separately, once for the identity module and once for the
authenticator module.

Also change the proxy module to retireve the pam target name from the domain
configuration so that it is possibile to create per-domain pam stacks.

With this modification it is actually possibile to use normal nss and pam
modules to perform a successful authentication (tested only with sudo so far)

Update exmples.
---
 server/examples/config.ldif         |   50 +++++++-----
 server/examples/sssdproxylocal      |    9 ++
 server/examples/sssdproxytest       |    9 ++
 server/examples/sudo                |    6 ++
 server/providers/data_provider_be.c |  155 ++++++++++++++++++++++++++++++-----
 server/providers/dp_backend.h       |   44 +++++-----
 server/providers/ldap_be.c          |   10 +-
 server/providers/proxy.c            |   73 ++++++++++++++---
 8 files changed, 275 insertions(+), 81 deletions(-)
 create mode 100644 server/examples/sssdproxylocal
 create mode 100644 server/examples/sssdproxytest
 create mode 100644 server/examples/sudo

diff --git a/server/examples/config.ldif b/server/examples/config.ldif
index b848e43..6101f08 100644
--- a/server/examples/config.ldif
+++ b/server/examples/config.ldif
@@ -15,31 +15,28 @@ activeServices: info
 dn: cn=nss,cn=services,cn=config
 cn: nss
 description: NSS Responder Configuration
-unixSocket: /var/lib/sss/pipes/nss
-command: /usr/libexec/sssd/sssd_nss
+filterGroups: root
+filterGroups: foo TEST
+filterUsers: root
+filterUsers: bar TEST
 
 dn: cn=dp,cn=services,cn=config
 cn: dp
 description: Data Provider Configuration
-command: /usr/libexec/sssd/sssd_dp
 
 dn: cn=monitor,cn=services,cn=config
 cn: monitor
 description: Monitor Configuration
 sbusTimeout: 10
-sbusAddress: unix:path=/var/lib/sss/pipes/private/dbus
 servicePingTime: 10
 
 dn: cn=pam,cn=services,cn=config
 cn: pam
-command: /usr/libexec/sssd/sssd_pam
 description: PAM Responder Configuration
-unixSocket: /var/lib/sss/pipes/pam
 
 dn: cn=info,cn=services,cn=config
 cn: info
 description: InfoPipe Configuration
-command: ./sbin/sssd_info
 
 dn: cn=domains,cn=config
 cn: domains
@@ -48,32 +45,43 @@ description: Domains served by SSSD
 dn: cn=LOCAL,cn=domains,cn=config
 cn: LOCAL
 description: Reserved domain for local configurations
-legacy: FALSE
 enumerate: 3
-
-dn: cn=EXAMPLE.COM,cn=domains,cn=config
-cn: EXAMPLE.COM
-description: Example domain served by IPA
-provider: ipa
-server: ipaserver1.example.com
-server: ipabackupserver.example.com
-legacy: FALSE
-enumerate: 0
+minId: 500
+maxId: 999
+legacy: TRUE
+libName: files
+libPath: /lib64/libnss_files.so.2
+magicPrivateGroups: FALSE
+provider: proxy
+auth-module: proxy
+pam-target: sssdproxylocal
 
 dn: cn=TEST,cn=domains,cn=config
 cn: TEST
 description: TEST Ldap domain
-provider: proxy
-command: ./sbin/sssd_be -d 2 --provider proxy --domain TEST
 libName: ldap
 libPath: /usr/lib64/libnss_ldap.so.2
 legacy: TRUE
-enumerate: 0
+enumerate: 3
+useFullyQualifiedNames: TRUE
+minId: 1000
+provider: proxy
+auth-module: proxy
+pam-target: sssdproxytest
 
 dn: cn=LDAPTEST,cn=domains,cn=config
 cn: LDAPTEST
 basedn: cn=LDAPTEST,sn=sysdb
-command: ./sbin/sssd_be --provider ldap --domain LDAPTEST
+command: /usr/libexec/sssd/sssd_be --provider ldap --domain LDAPTEST
 description: TEST PAM Ldap domain
 provider: ldap
 userSearchBase: ou=user,dc=my-domain,dc=com
+
+dn: cn=EXAMPLE.COM,cn=domains,cn=config
+cn: EXAMPLE.COM
+description: Example domain served by IPA
+provider: ipa
+server: ipaserver1.example.com
+server: ipabackupserver.example.com
+legacy: FALSE
+enumerate: 0
diff --git a/server/examples/sssdproxylocal b/server/examples/sssdproxylocal
new file mode 100644
index 0000000..1bc47f8
--- /dev/null
+++ b/server/examples/sssdproxylocal
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth        sufficient    pam_unix.so
+auth        requisite     pam_succeed_if.so uid >= 500 quiet
+auth        required      pam_deny.so
+
+account     required      pam_unix.so
+account     sufficient    pam_succeed_if.so uid < 500 quiet
+account     required      pam_permit.so
+
diff --git a/server/examples/sssdproxytest b/server/examples/sssdproxytest
new file mode 100644
index 0000000..9c5cb4a
--- /dev/null
+++ b/server/examples/sssdproxytest
@@ -0,0 +1,9 @@
+#%PAM-1.0
+auth        sufficient    pam_ldap.so debug
+auth        requisite     pam_succeed_if.so uid >= 1000 quiet
+auth        required      pam_deny.so
+
+account     required      pam_ldap.so debug
+account     sufficient    pam_succeed_if.so uid < 1000 quiet
+account     required      pam_permit.so
+
diff --git a/server/examples/sudo b/server/examples/sudo
new file mode 100644
index 0000000..4af91ba
--- /dev/null
+++ b/server/examples/sudo
@@ -0,0 +1,6 @@
+#%PAM-1.0
+auth     required pam_sss.so
+account  required pam_sss.so
+password required pam_sss.so
+session    optional     pam_keyinit.so revoke
+session    required     pam_limits.so
diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 4e99f56..61844bb 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -49,8 +49,6 @@
 
 #define BE_CONF_ENTRY "config/domains/%s"
 
-typedef int (*be_init_fn_t)(TALLOC_CTX *, struct be_mod_ops **, void **);
-
 static int service_identity(DBusMessage *message, struct sbus_conn_ctx *sconn);
 static int service_pong(DBusMessage *message, struct sbus_conn_ctx *sconn);
 
@@ -305,7 +303,7 @@ static int be_check_online(DBusMessage *message, struct sbus_conn_ctx *sconn)
 
     be_req->req_data = req;
 
-    ret = be_file_request(ctx, ctx->ops->check_online, be_req);
+    ret = be_file_request(ctx, ctx->id_ops->check_online, be_req);
     if (ret != EOK) {
         online = MOD_OFFLINE;
         err_maj = DP_ERR_FATAL;
@@ -482,7 +480,7 @@ static int be_get_account_info(DBusMessage *message, struct sbus_conn_ctx *sconn
 
     be_req->req_data = req;
 
-    ret = be_file_request(ctx, ctx->ops->get_account_info, be_req);
+    ret = be_file_request(ctx, ctx->id_ops->get_account_info, be_req);
     if (ret != EOK) {
         err_maj = DP_ERR_FATAL;
         err_min = ret;
@@ -588,7 +586,7 @@ static int be_pam_handler(DBusMessage *message, struct sbus_conn_ctx *sconn)
     be_req->pvt = reply;
     be_req->req_data = pd;
 
-    ret = be_file_request(ctx, ctx->ops->pam_handler, be_req);
+    ret = be_file_request(ctx, ctx->auth_ops->pam_handler, be_req);
     if (ret != EOK) {
         pam_status = PAM_SYSTEM_ERR;
         goto done;
@@ -698,8 +696,7 @@ static int be_cli_init(struct be_ctx *ctx)
 }
 
 static int be_finalize(struct be_ctx *ctx);
-static void be_shutdown(struct be_req *req, int status,
-                        const char *errstr);
+static void be_shutdown(struct be_req *req, int status, const char *errstr);
 
 static void be_cli_reconnect_init(struct sbus_conn_ctx *sconn, int status, void *pvt)
 {
@@ -730,37 +727,76 @@ static void be_cli_reconnect_init(struct sbus_conn_ctx *sconn, int status, void
     /* Kill the backend and let the monitor restart it */
     ret = be_finalize(be_ctx);
     if (ret != EOK) {
-        DEBUG(0, ("Finalizing back-end failed with error [%d] [%s]", ret, strerror(ret)));
+        DEBUG(0, ("Finalizing back-end failed with error [%d] [%s]\n",
+                  ret, strerror(ret)));
         be_shutdown(NULL, ret, NULL);
     }
 }
 
-static void be_shutdown(struct be_req *req, int status,
-                        const char *errstr)
+static void be_shutdown(struct be_req *req, int status, const char *errstr)
 {
     /* Nothing left to do but exit() */
     if (status == EOK)
         exit(0);
 
     /* Something went wrong in finalize */
+    DEBUG(0, ("Finalizing auth module failed with error [%d] [%s]\n",
+              status, errstr ? : strerror(status)));
+
     exit(1);
 }
 
-static int be_finalize(struct be_ctx *ctx)
+static void be_id_shutdown(struct be_req *req, int status, const char *errstr)
 {
+    struct be_req *shutdown_req;
+    struct be_ctx *ctx;
     int ret;
-    struct be_req *shutdown_req = talloc_zero(ctx, struct be_req);
+
+    if (status != EOK) {
+        /* Something went wrong in finalize */
+        DEBUG(0, ("Finalizing auth module failed with error [%d] [%s]\n",
+                  status, errstr ? : strerror(status)));
+    }
+
+    ctx = req->be_ctx;
+
+    /* Now shutdown the id module too */
+    shutdown_req = talloc_zero(ctx, struct be_req);
     if (!shutdown_req) {
         ret = ENOMEM;
         goto fail;
     }
 
     shutdown_req->be_ctx = ctx;
-    shutdown_req->fn = be_shutdown;
+    shutdown_req->fn = be_id_shutdown;
+
+    shutdown_req->pvt = ctx->pvt_id_data;
+
+    ret = be_file_request(ctx, ctx->id_ops->finalize, shutdown_req);
+    if (ret == EOK)
+        return;
+
+fail:
+    /* If we got here, we couldn't shut down cleanly. */
+    be_shutdown(NULL, ret, NULL);
+}
+
+static int be_finalize(struct be_ctx *ctx)
+{
+    struct be_req *shutdown_req;
+    int ret;
+
+    shutdown_req = talloc_zero(ctx, struct be_req);
+    if (!shutdown_req) {
+        ret = ENOMEM;
+        goto fail;
+    }
 
-    shutdown_req->pvt = ctx->pvt_data;
+    shutdown_req->be_ctx = ctx;
+    shutdown_req->fn = be_id_shutdown;
+    shutdown_req->pvt = ctx->pvt_auth_data;
 
-    ret = be_file_request(ctx, ctx->ops->finalize, shutdown_req);
+    ret = be_file_request(ctx, ctx->auth_ops->finalize, shutdown_req);
     if (ret == EOK) return EOK;
 
 fail:
@@ -769,13 +805,13 @@ fail:
     return ret;
 }
 
-static int load_backend(struct be_ctx *ctx)
+static int load_id_backend(struct be_ctx *ctx)
 {
     TALLOC_CTX *tmp_ctx;
     char *path;
     void *handle;
     char *mod_init_fn_name;
-    be_init_fn_t mod_init_fn;
+    be_id_init_fn_t mod_init_fn;
     int ret;
 
     tmp_ctx = talloc_new(ctx);
@@ -804,7 +840,7 @@ static int load_backend(struct be_ctx *ctx)
         goto done;
     }
 
-    mod_init_fn = (be_init_fn_t)dlsym(handle, mod_init_fn_name);
+    mod_init_fn = (be_id_init_fn_t)dlsym(handle, mod_init_fn_name);
     if (!mod_init_fn) {
         DEBUG(0, ("Unable to load init fn from module %s, error: %s\n",
                   ctx->name, dlerror()));
@@ -812,7 +848,7 @@ static int load_backend(struct be_ctx *ctx)
         goto done;
     }
 
-    ret = mod_init_fn(ctx, &ctx->ops, &ctx->pvt_data);
+    ret = mod_init_fn(ctx, &ctx->id_ops, &ctx->pvt_id_data);
     if (ret != EOK) {
         DEBUG(0, ("Error (%d) in module (%s) initialization!\n",
                   ret, ctx->name));
@@ -826,6 +862,75 @@ done:
     return ret;
 }
 
+static int load_auth_backend(struct be_ctx *ctx)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *mod_name;
+    char *path;
+    void *handle;
+    char *mod_init_fn_name;
+    be_auth_init_fn_t mod_init_fn;
+    int ret;
+
+    tmp_ctx = talloc_new(ctx);
+    if (!tmp_ctx) {
+        return ENOMEM;
+    }
+
+    ret = confdb_get_string(ctx->cdb, tmp_ctx, ctx->conf_path,
+                            "auth-module", NULL, &mod_name);
+    if (ret != EOK) {
+        ret = EFAULT;
+        goto done;
+    }
+    if (!mod_name) {
+        ret = ENOENT;
+        goto done;
+    }
+
+    path = talloc_asprintf(tmp_ctx, "%s/libsss_%s.so",
+                           DATA_PROVIDER_PLUGINS_PATH, mod_name);
+    if (!path) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    handle = dlopen(path, RTLD_NOW);
+    if (!handle) {
+        DEBUG(0, ("Unable to load %s module with path (%s), error: %s\n",
+                  mod_name, path, dlerror()));
+        ret = ELIBACC;
+        goto done;
+    }
+
+    mod_init_fn_name = talloc_asprintf(tmp_ctx, "sssm_%s_auth_init", mod_name);
+    if (!mod_init_fn_name) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    mod_init_fn = (be_auth_init_fn_t)dlsym(handle, mod_init_fn_name);
+    if (!mod_init_fn) {
+        DEBUG(0, ("Unable to load init fn from module %s, error: %s\n",
+                  mod_name, dlerror()));
+        ret = ELIBBAD;
+        goto done;
+    }
+
+    ret = mod_init_fn(ctx, &ctx->auth_ops, &ctx->pvt_auth_data);
+    if (ret != EOK) {
+        DEBUG(0, ("Error (%d) in module (%s) initialization!\n",
+                  ret, mod_name));
+        goto done;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
 int be_process_init(TALLOC_CTX *mem_ctx,
                     const char *be_name,
                     const char *be_domain,
@@ -869,12 +974,22 @@ int be_process_init(TALLOC_CTX *mem_ctx,
         return ret;
     }
 
-    ret = load_backend(ctx);
+    ret = load_id_backend(ctx);
     if (ret != EOK) {
         DEBUG(0, ("fatal error initializing data providers\n"));
         return ret;
     }
 
+    ret = load_auth_backend(ctx);
+    if (ret != EOK) {
+        if (ret != ENOENT) {
+            DEBUG(0, ("fatal error initializing data providers\n"));
+            return ret;
+        }
+        DEBUG(1, ("No authentication module provided for [%s] !!\n",
+                  be_domain));
+    }
+
     return EOK;
 }
 
diff --git a/server/providers/dp_backend.h b/server/providers/dp_backend.h
index 12cfb3a..2d1cd83 100644
--- a/server/providers/dp_backend.h
+++ b/server/providers/dp_backend.h
@@ -27,10 +27,15 @@
 #include "responder/pam/pamsrv.h"
 
 struct be_ctx;
+struct be_id_ops;
+struct be_auth_ops;
+struct be_req;
 
+typedef int (*be_id_init_fn_t)(TALLOC_CTX *, struct be_id_ops **, void **);
+typedef int (*be_auth_init_fn_t)(TALLOC_CTX *, struct be_auth_ops **, void **);
 typedef void (*be_shutdown_fn)(void *);
-
-struct be_mod_ops;
+typedef void (*be_req_fn_t)(struct be_req *);
+typedef void (*be_async_callback_t)(struct be_req *, int, const char *);
 
 struct be_ctx {
     struct tevent_context *ev;
@@ -42,14 +47,24 @@ struct be_ctx {
     const char *domain;
     const char *identity;
     const char *conf_path;
-    struct be_mod_ops *ops;
-    void *pvt_data;
-    be_shutdown_fn shutdown;
+
+    struct be_id_ops *id_ops;
+    void *pvt_id_data;
+
+    struct be_auth_ops *auth_ops;
+    void *pvt_auth_data;
 };
 
-struct be_req;
+struct be_id_ops {
+    be_req_fn_t check_online;
+    be_req_fn_t get_account_info;
+    be_req_fn_t finalize;
+};
 
-typedef void (*be_async_callback_t)(struct be_req *, int, const char *);
+struct be_auth_ops {
+    be_req_fn_t pam_handler;
+    be_req_fn_t finalize;
+};
 
 struct be_req {
     struct be_ctx *be_ctx;
@@ -70,19 +85,4 @@ struct be_online_req {
     int online;
 };
 
-struct be_pam_handler {
-    int pam_status;
-    const char *domain;
-    struct pam_data *pd;
-};
-
-typedef void (*be_req_fn_t)(struct be_req *);
-
-struct be_mod_ops {
-    be_req_fn_t check_online;
-    be_req_fn_t get_account_info;
-    be_req_fn_t pam_handler;
-    be_req_fn_t finalize;
-};
-
 #endif /* __DP_BACKEND_H___ */
diff --git a/server/providers/ldap_be.c b/server/providers/ldap_be.c
index 9fe2564..2c075bd 100644
--- a/server/providers/ldap_be.c
+++ b/server/providers/ldap_be.c
@@ -592,7 +592,7 @@ static void sdap_pam_handler(struct be_req *req)
 
     pd = talloc_get_type(req->req_data, struct pam_data);
 
-    sdap_ctx = talloc_get_type(req->be_ctx->pvt_data, struct sdap_ctx);
+    sdap_ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct sdap_ctx);
 
     lr = talloc(req, struct sdap_req);
 
@@ -628,15 +628,15 @@ static void sdap_shutdown(struct be_req *req)
     req->fn(req, EOK, NULL);
 }
 
-struct be_mod_ops sdap_mod_ops = {
-    .check_online = NULL,
-    .get_account_info = NULL,
+struct be_auth_ops sdap_mod_ops = {
     .pam_handler = sdap_pam_handler,
     .finalize = sdap_shutdown
 };
 
 
-int sssm_ldap_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_data)
+int sssm_ldap_auth_init(struct be_ctx *bectx,
+                        struct be_auth_ops **ops,
+                        void **pvt_data)
 {
     struct sdap_ctx *ctx;
     char *ldap_uri;
diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index c87b482..1b4a830 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -61,6 +61,10 @@ struct proxy_ctx {
     struct proxy_nss_ops ops;
 };
 
+struct proxy_auth_ctx {
+    char *pam_target;
+};
+
 struct authtok_conv {
     char *authtok;
     char *oldauthtok;
@@ -84,7 +88,7 @@ static int proxy_internal_conv(int num_msg, const struct pam_message **msgm,
     for (i=0; i < num_msg; i++) {
         switch( msgm[i]->msg_style ) {
             case PAM_PROMPT_ECHO_OFF:
-                DEBUG(4, ("Conversation message: %s.\n", msgm[i]->msg));
+                DEBUG(4, ("Conversation message: [%s]\n", msgm[i]->msg));
                 reply[i].resp_retcode = 0;
                 reply[i].resp = strdup(auth_data->authtok);
                 break;
@@ -112,14 +116,16 @@ static void proxy_pam_handler(struct be_req *req) {
     struct authtok_conv *auth_data;
     struct pam_conv conv;
     struct pam_data *pd;
+    struct proxy_auth_ctx *ctx;;
 
+    ctx = talloc_get_type(req->be_ctx->pvt_auth_data, struct proxy_auth_ctx);
     pd = talloc_get_type(req->req_data, struct pam_data);
 
     conv.conv=proxy_internal_conv;
     auth_data = talloc_zero(req->be_ctx, struct authtok_conv);
     conv.appdata_ptr=auth_data;
 
-    ret = pam_start("sssd_be_test", pd->user, &conv, &pamh);
+    ret = pam_start(ctx->pam_target, pd->user, &conv, &pamh);
     if (ret == PAM_SUCCESS) {
         DEBUG(1, ("Pam transaction started.\n"));
         pam_set_item(pamh, PAM_TTY, pd->tty);
@@ -279,7 +285,7 @@ static void get_pw_name(struct be_req *req, char *name)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -340,7 +346,7 @@ static void get_pw_uid(struct be_req *req, uid_t uid)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -478,7 +484,7 @@ static void enum_users(struct be_req *req)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -551,7 +557,7 @@ static void get_gr_name(struct be_req *req, char *name)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -611,7 +617,7 @@ static void get_gr_gid(struct be_req *req, gid_t gid)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -741,7 +747,7 @@ static void enum_groups(struct be_req *req)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -920,7 +926,7 @@ static void get_initgr_user(struct be_req *req, char *name)
     struct proxy_data *data;
     int ret;
 
-    ctx = talloc_get_type(req->be_ctx->pvt_data, struct proxy_ctx);
+    ctx = talloc_get_type(req->be_ctx->pvt_id_data, struct proxy_ctx);
 
     data = talloc_zero(req, struct proxy_data);
     if (!data)
@@ -1109,13 +1115,23 @@ static void proxy_shutdown(struct be_req *req)
     req->fn(req, EOK, NULL);
 }
 
-struct be_mod_ops proxy_mod_ops = {
+static void proxy_auth_shutdown(struct be_req *req)
+{
+    talloc_free(req->be_ctx->pvt_auth_data);
+    req->fn(req, EOK, NULL);
+}
+
+struct be_id_ops proxy_id_ops = {
     .check_online = proxy_check_online,
     .get_account_info = proxy_get_account_info,
-    .pam_handler = proxy_pam_handler,
     .finalize = proxy_shutdown
 };
 
+struct be_auth_ops proxy_auth_ops = {
+    .pam_handler = proxy_pam_handler,
+    .finalize = proxy_auth_shutdown
+};
+
 static void *proxy_dlsym(void *handle, const char *functemp, char *libname)
 {
     char *funcname;
@@ -1130,7 +1146,8 @@ static void *proxy_dlsym(void *handle, const char *functemp, char *libname)
     return funcptr;
 }
 
-int sssm_proxy_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_data)
+int sssm_proxy_init(struct be_ctx *bectx,
+                    struct be_id_ops **ops, void **pvt_data)
 {
     struct proxy_ctx *ctx;
     char *libname;
@@ -1240,7 +1257,7 @@ int sssm_proxy_init(struct be_ctx *bectx, struct be_mod_ops **ops, void **pvt_da
                   "full groups enumeration!\n", libname));
     }
 
-    *ops = &proxy_mod_ops;
+    *ops = &proxy_id_ops;
     *pvt_data = ctx;
     ret = EOK;
 
@@ -1250,3 +1267,33 @@ done:
     }
     return ret;
 }
+
+int sssm_proxy_auth_init(struct be_ctx *bectx,
+                         struct be_auth_ops **ops, void **pvt_data)
+{
+    struct proxy_auth_ctx *ctx;
+    int ret;
+
+    ctx = talloc(bectx, struct proxy_auth_ctx);
+    if (!ctx) return ENOMEM;
+
+    ret = confdb_get_string(bectx->cdb, ctx, bectx->conf_path,
+                           "pam-target", NULL, &ctx->pam_target);
+    if (ret != EOK) goto done;
+    if (!ctx->pam_target) {
+        ctx->pam_target = talloc_strdup(ctx, "sssd_pam_proxy_default");
+        if (!ctx->pam_target) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    *ops = &proxy_auth_ops;
+    *pvt_data = ctx;
+
+done:
+    if (ret != EOK) {
+        talloc_free(ctx);
+    }
+    return ret;
+}
-- 
1.6.0.6

>From 186369b0a2e61527baf4bb5cb9682cf600e4fc96 Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce redhat com>
Date: Sat, 4 Apr 2009 12:24:45 -0400
Subject: [PATCH] Use info in the domain entry to determine action.

This way LOCAL domains backed by files works as expected too.
Tested with nss_files + pam_unix
---
 server/responder/pam/pamsrv_cmd.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 06a230b..69f198c 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -194,6 +194,7 @@ done:
 
 static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
 {
+    struct sss_domain_info *info;
     uint8_t *body;
     size_t blen;
     int ret;
@@ -229,7 +230,17 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
         DEBUG(4, ("Using default domain [%s].\n", pd->domain));
     }
 
-    if ( strncasecmp(pd->domain,"LOCAL",5) == 0 ) {
+    if (pd->domain) {
+        /* Check for registered domain */
+        info = btreemap_get_value(cctx->rctx->domain_map,
+                                    (void *)(pd->domain));
+        if (!info) {
+            talloc_free(pd);
+            return EINVAL;
+        }
+    }
+
+    if (!info->provider) {
         return LOCAL_pam_handler(cctx, pam_reply, pd);
     };
 
-- 
1.6.0.6

>From b1475364687666b38309a286f7ce2ecd25197cf9 Mon Sep 17 00:00:00 2001
From: Simo Sorce <ssorce redhat com>
Date: Mon, 6 Apr 2009 15:54:00 -0400
Subject: [PATCH] Unify name parsing and reposnder headers

Use common sss_parse_name function in all responders
Simplify responder headers by combining common,cmd,dp in one header and
add name parse structure as part of the common responder context.
---
 server/responder/common/responder.h        |  119 +++++++++++++
 server/responder/common/responder_cmd.c    |    2 +-
 server/responder/common/responder_cmd.h    |   87 ----------
 server/responder/common/responder_common.c |  136 ++++++++++++---
 server/responder/common/responder_common.h |   26 ---
 server/responder/common/responder_dp.c     |    2 +-
 server/responder/common/responder_dp.h     |    3 -
 server/responder/nss/nsssrv.c              |   28 +---
 server/responder/nss/nsssrv.h              |   10 +-
 server/responder/nss/nsssrv_cmd.c          |  257 +++++++++++++++-------------
 server/responder/pam/pamsrv.c              |    2 -
 server/responder/pam/pamsrv.h              |    2 +-
 server/responder/pam/pamsrv_cmd.c          |   65 ++++----
 13 files changed, 412 insertions(+), 327 deletions(-)
 create mode 100644 server/responder/common/responder.h
 delete mode 100644 server/responder/common/responder_cmd.h
 delete mode 100644 server/responder/common/responder_common.h
 delete mode 100644 server/responder/common/responder_dp.h

diff --git a/server/responder/common/responder.h b/server/responder/common/responder.h
new file mode 100644
index 0000000..4b6bfee
--- /dev/null
+++ b/server/responder/common/responder.h
@@ -0,0 +1,119 @@
+/*
+   SSSD
+
+   SSS Client Responder, header file
+
+   Copyright (C) Simo Sorce <ssorce redhat com>	2008
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SSS_RESPONDER_H__
+#define __SSS_RESPONDER_H__
+
+#include <stdint.h>
+#include <sys/un.h>
+#include <pcre.h>
+#include "config.h"
+#include "talloc.h"
+#include "tevent.h"
+#include "ldb.h"
+#include "sbus/sssd_dbus.h"
+#include "../sss_client/sss_cli.h"
+#include "util/btreemap.h"
+
+/* needed until nsssrv.h is updated */
+struct cli_request {
+
+    /* original request from the wire */
+    struct sss_packet *in;
+
+    /* reply data */
+    struct sss_packet *out;
+};
+
+struct sss_names_ctx {
+    char *re_pattern;
+    char *fq_fmt;
+
+    pcre *re;
+};
+
+struct resp_ctx {
+    struct tevent_context *ev;
+    struct tevent_fd *lfde;
+    int lfd;
+    struct tevent_fd *priv_lfde;
+    int priv_lfd;
+    struct sysdb_ctx *sysdb;
+    struct confdb_ctx *cdb;
+    const char *sock_name;
+    const char *priv_sock_name;
+    struct service_sbus_ctx *ss_ctx;
+    struct service_sbus_ctx *dp_ctx;
+
+    struct btreemap *domain_map;
+    char *default_domain;
+
+    struct sbus_method *sss_sbus_methods;
+    struct sss_cmd_table *sss_cmds;
+    const char *sss_pipe_name;
+    const char *confdb_service_path;
+    struct sbus_method *dp_methods;
+
+    struct sss_names_ctx *names;
+
+    void *pvt_ctx;
+};
+
+struct cli_ctx {
+    struct tevent_context *ev;
+    struct resp_ctx *rctx;
+    int cfd;
+    struct tevent_fd *cfde;
+    struct sockaddr_un addr;
+    struct cli_request *creq;
+    int priv;
+};
+
+struct sss_cmd_table {
+    enum sss_cli_command cmd;
+    int (*fn)(struct cli_ctx *cctx);
+};
+
+/* responder_common.c */
+int sss_process_init(TALLOC_CTX *mem_ctx,
+                     struct tevent_context *ev,
+                     struct confdb_ctx *cdb,
+                     struct sbus_method sss_sbus_methods[],
+                     struct sss_cmd_table sss_cmds[],
+                     const char *sss_pipe_name,
+                     const char *sss_priv_pipe_name,
+                     const char *confdb_service_path,
+                     struct sbus_method dp_methods[],
+                     struct resp_ctx **responder_ctx);
+
+int sss_parse_name(TALLOC_CTX *memctx,
+                   struct sss_names_ctx *snctx,
+                   const char *orig, char **domain, char **name);
+
+/* responder_cmd.c */
+int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds);
+void sss_cmd_done(struct cli_ctx *cctx, void *freectx);
+int sss_cmd_get_version(struct cli_ctx *cctx);
+
+/* responder_dp.c */
+int sss_dp_init(struct resp_ctx *rctx, struct sbus_method dp_methods[]);
+
+#endif /* __SSS_RESPONDER_H__ */
diff --git a/server/responder/common/responder_cmd.c b/server/responder/common/responder_cmd.c
index a434b3e..33caa03 100644
--- a/server/responder/common/responder_cmd.c
+++ b/server/responder/common/responder_cmd.c
@@ -20,7 +20,7 @@
 */
 #include <errno.h>
 #include "util/util.h"
-#include "responder/common/responder_cmd.h"
+#include "responder/common/responder.h"
 #include "responder/common/responder_packet.h"
 
 
diff --git a/server/responder/common/responder_cmd.h b/server/responder/common/responder_cmd.h
deleted file mode 100644
index eb3bd08..0000000
--- a/server/responder/common/responder_cmd.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-   SSSD
-
-   SSS Client Responder, header file
-
-   Copyright (C) Simo Sorce <ssorce redhat com>	2008
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef __SSSSRV_CMD_H__
-#define __SSSSRV_CMD_H__
-
-#include <stdint.h>
-#include <sys/un.h>
-#include "talloc.h"
-#include "tevent.h"
-#include "ldb.h"
-#include "../sss_client/sss_cli.h"
-#include "util/btreemap.h"
-
-/* needed until nsssrv.h is updated */
-struct cli_request {
-
-    /* original request from the wire */
-    struct sss_packet *in;
-
-    /* reply data */
-    struct sss_packet *out;
-};
-
-struct resp_ctx {
-    struct tevent_context *ev;
-    struct tevent_fd *lfde;
-    int lfd;
-    struct tevent_fd *priv_lfde;
-    int priv_lfd;
-    struct sysdb_ctx *sysdb;
-    struct confdb_ctx *cdb;
-    const char *sock_name;
-    const char *priv_sock_name;
-    struct service_sbus_ctx *ss_ctx;
-    struct service_sbus_ctx *dp_ctx;
-
-    struct btreemap *domain_map;
-    char *default_domain;
-
-    struct sbus_method *sss_sbus_methods;
-    struct sss_cmd_table *sss_cmds;
-    const char *sss_pipe_name;
-    const char *confdb_service_path;
-    struct sbus_method *dp_methods;
-
-    void *pvt_ctx;
-};
-
-struct cli_ctx {
-    struct tevent_context *ev;
-    struct resp_ctx *rctx;
-    int cfd;
-    struct tevent_fd *cfde;
-    struct sockaddr_un addr;
-    struct cli_request *creq;
-    int priv;
-};
-
-struct sss_cmd_table {
-    enum sss_cli_command cmd;
-    int (*fn)(struct cli_ctx *cctx);
-};
-
-int sss_cmd_execute(struct cli_ctx *cctx, struct sss_cmd_table *sss_cmds);
-void sss_cmd_done(struct cli_ctx *cctx, void *freectx);
-int sss_cmd_get_version(struct cli_ctx *cctx);
-
-#endif /* __SSSSRV_CMD_H__ */
diff --git a/server/responder/common/responder_common.c b/server/responder/common/responder_common.c
index fa024d5..855c78a 100644
--- a/server/responder/common/responder_common.c
+++ b/server/responder/common/responder_common.c
@@ -36,15 +36,15 @@
 #include "dbus/dbus.h"
 #include "sbus/sssd_dbus.h"
 #include "util/btreemap.h"
-#include "responder/common/responder_common.h"
+#include "responder/common/responder.h"
 #include "responder/common/responder_packet.h"
-#include "responder/common/responder_cmd.h"
-#include "responder/common/responder_dp.h"
 #include "providers/data_provider.h"
 #include "monitor/monitor_sbus.h"
 #include "monitor/monitor_interfaces.h"
 #include "sbus/sbus_client.h"
 
+#define NAMES_CONFIG "config/names"
+
 static void set_nonblocking(int fd)
 {
     unsigned v;
@@ -487,6 +487,62 @@ done:
     return retval;
 }
 
+int sss_names_init(struct resp_ctx *rctx)
+{
+    struct sss_names_ctx *ctx;
+    const char *errstr;
+    int errval;
+    int errpos;
+    int ret;
+
+    ctx = talloc_zero(rctx, struct sss_names_ctx);
+    if (!ctx) return ENOMEM;
+
+    ret = confdb_get_string(rctx->cdb, ctx, NAMES_CONFIG,
+                            "re-expression", NULL, &ctx->re_pattern);
+    if (ret != EOK) goto done;
+
+    if (!ctx->re_pattern) {
+        ctx->re_pattern = talloc_strdup(ctx,
+                                "(?<name>[^ ]+)@?(?<domain>[^ ]*$)");
+        if (!ctx->re_pattern) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    ret = confdb_get_string(rctx->cdb, ctx, NAMES_CONFIG,
+                            "full-name-format", NULL, &ctx->fq_fmt);
+    if (ret != EOK) goto done;
+
+    if (!ctx->fq_fmt) {
+        ctx->fq_fmt = talloc_strdup(ctx, "%1$s %2$s");
+        if (!ctx->fq_fmt) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    ctx->re = pcre_compile2(ctx->re_pattern,
+                            PCRE_DUPNAMES | PCRE_EXTENDED,
+                            &errval, &errstr, &errpos, NULL);
+    if (!ctx->re) {
+        DEBUG(1, ("Invalid Regular Expression pattern at position %d."
+                  " (Error: %d [%s])\n", errpos, errval, errstr));
+        ret = EFAULT;
+        goto done;
+    }
+
+    rctx->names = ctx;
+    ret = EOK;
+
+done:
+    if (ret != EOK) {
+        talloc_free(ctx);
+    }
+    return ret;
+}
+
 int sss_process_init(TALLOC_CTX *mem_ctx,
                      struct tevent_context *ev,
                      struct confdb_ctx *cdb,
@@ -539,6 +595,12 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
         return ret;
     }
 
+    ret = sss_names_init(rctx);
+    if (ret != EOK) {
+        DEBUG(0, ("fatal error initializing regex data\n"));
+        return ret;
+    }
+
     /* after all initializations we are ready to listen on our socket */
     ret = set_unix_socket(rctx);
     if (ret != EOK) {
@@ -553,33 +615,55 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
 }
 
 int sss_parse_name(TALLOC_CTX *memctx,
-                          const char *fullname,
-                          struct btreemap *domain_map,
-                          const char **domain, const char **name) {
-    char *delim;
-    struct btreemap *node;
-    int ret;
+                   struct sss_names_ctx *snctx,
+                   const char *orig, char **domain, char **name)
+{
+    pcre *re = snctx->re;
+    const char *result;
+    int ovec[30];
+    int origlen;
+    int ret, strnum;
 
-    if ((delim = strchr(fullname, SSS_DOMAIN_DELIM)) != NULL) {
-
-        /* Check for registered domain */
-        ret = btreemap_search_key(domain_map, (void *)(delim+1), &node);
-        if (ret != BTREEMAP_FOUND) {
-            /* No such domain was registered. Return EINVAL.
-             * TODO: alternative approach?
-             * Alternatively, we could simply fail down to
-             * below, treating the entire construct as the
-             * full name if the domain is unspecified.
-             */
-            return EINVAL;
-        }
+    origlen = strlen(orig);
+
+    ret = pcre_exec(re, NULL, orig, origlen, 0, PCRE_NOTEMPTY, ovec, 30);
+    if (ret < 0) {
+        DEBUG(2, ("PCRE Matching error, %d\n", ret));
+        return EINVAL;
+    }
 
-        *name = talloc_strndup(memctx, fullname, delim-fullname);
-        *domain = talloc_strdup(memctx, delim+1);
+    if (ret == 0) {
+        DEBUG(1, ("Too many matches, the pattern is invalid.\n"));
     }
-    else {
-        *name = talloc_strdup(memctx, fullname);
+
+    strnum = ret;
+
+    result = NULL;
+    ret = pcre_get_named_substring(re, orig, ovec, strnum, "name", &result);
+    if (ret < 0  || !result) {
+        DEBUG(2, ("Name not found!\n"));
+        return EINVAL;
+    }
+    *name = talloc_strdup(memctx, result);
+    pcre_free_substring(result);
+    if (!*name) return ENOMEM;
+
+
+    result = NULL;
+    ret = pcre_get_named_substring(re, orig, ovec, strnum, "domain", &result);
+    if (ret < 0  || !result) {
+        DEBUG(4, ("Domain not provided!\n"));
         *domain = NULL;
+    } else {
+        /* ignore "" string */
+        if (*result) {
+            *domain = talloc_strdup(memctx, result);
+            pcre_free_substring(result);
+            if (!*domain) return ENOMEM;
+        } else {
+            pcre_free_substring(result);
+            *domain = NULL;
+        }
     }
 
     return EOK;
diff --git a/server/responder/common/responder_common.h b/server/responder/common/responder_common.h
deleted file mode 100644
index 8a7af08..0000000
--- a/server/responder/common/responder_common.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "config.h"
-#include "sbus/sssd_dbus.h"
-#include "responder/common/responder_cmd.h"
-#include "util/btreemap.h"
-
-/* SSS_DOMAIN_DELIM can be specified in config.h */
-#ifndef SSS_DOMAIN_DELIM
-#define SSS_DOMAIN_DELIM '@'
-#endif
-
-
-int sss_process_init(TALLOC_CTX *mem_ctx,
-                     struct tevent_context *ev,
-                     struct confdb_ctx *cdb,
-                     struct sbus_method sss_sbus_methods[],
-                     struct sss_cmd_table sss_cmds[],
-                     const char *sss_pipe_name,
-                     const char *sss_priv_pipe_name,
-                     const char *confdb_service_path,
-                     struct sbus_method dp_methods[],
-                     struct resp_ctx **responder_ctx);
-
-int sss_parse_name(TALLOC_CTX *memctx,
-                   const char *fullname,
-                   struct btreemap *domain_map,
-                   const char **domain, const char **name);
diff --git a/server/responder/common/responder_dp.c b/server/responder/common/responder_dp.c
index 937b48d..7fc7e0b 100644
--- a/server/responder/common/responder_dp.c
+++ b/server/responder/common/responder_dp.c
@@ -3,7 +3,7 @@
 #include <time.h>
 #include "util/util.h"
 #include "responder/common/responder_packet.h"
-#include "responder/common/responder_common.h"
+#include "responder/common/responder.h"
 #include "providers/data_provider.h"
 #include "sbus/sbus_client.h"
 #include "providers/dp_sbus.h"
diff --git a/server/responder/common/responder_dp.h b/server/responder/common/responder_dp.h
deleted file mode 100644
index 528490f..0000000
--- a/server/responder/common/responder_dp.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "sbus/sssd_dbus.h"
-
-int sss_dp_init(struct resp_ctx *rctx, struct sbus_method dp_methods[]);
diff --git a/server/responder/nss/nsssrv.c b/server/responder/nss/nsssrv.c
index 4f9713b..834c42d 100644
--- a/server/responder/nss/nsssrv.c
+++ b/server/responder/nss/nsssrv.c
@@ -123,7 +123,7 @@ static int nss_get_config(struct nss_ctx *nctx,
                           struct confdb_ctx *cdb)
 {
     TALLOC_CTX *tmpctx;
-    const char *domain, *name;
+    char *domain, *name;
     const char **domains;
     char **filter_list;
     int ret, num, i, j;
@@ -150,8 +150,8 @@ static int nss_get_config(struct nss_ctx *nctx,
                            "filterUsers", &filter_list);
     if (ret != EOK) goto done;
     for (i = 0; filter_list[i]; i++) {
-        ret = nss_parse_name(tmpctx, nctx, filter_list[i],
-                             &domain, &name);
+        ret = sss_parse_name(tmpctx, nctx->rctx->names,
+                             filter_list[i], &domain, &name);
         if (ret != EOK) {
             DEBUG(1, ("Invalid name in filterUsers list: [%s] (%d)\n",
                      filter_list[i], ret));
@@ -192,8 +192,8 @@ static int nss_get_config(struct nss_ctx *nctx,
                            "filterGroups", &filter_list);
     if (ret != EOK) goto done;
     for (i = 0; filter_list[i]; i++) {
-        ret = nss_parse_name(tmpctx, nctx, filter_list[i],
-                             &domain, &name);
+        ret = sss_parse_name(tmpctx, nctx->rctx->names,
+                             filter_list[i], &domain, &name);
         if (ret != EOK) {
             DEBUG(1, ("Invalid name in filterGroups list: [%s] (%d)\n",
                      filter_list[i], ret));
@@ -235,22 +235,6 @@ done:
     return ret;
 }
 
-static void *nss_pcre_malloc(size_t size)
-{
-    return talloc_named_const(NULL, size, "nss_pcre_malloc");
-}
-
-static void nss_pcre_free(void *ctx)
-{
-    talloc_free(ctx);
-}
-
-void nss_pcre_setup(void)
-{
-    pcre_malloc = nss_pcre_malloc;
-    pcre_free = nss_pcre_free;
-}
-
 int nss_process_init(TALLOC_CTX *mem_ctx,
                      struct tevent_context *ev,
                      struct confdb_ctx *cdb)
@@ -260,8 +244,6 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
     struct nss_ctx *nctx;
     int ret;
 
-    nss_pcre_setup();
-
     nctx = talloc_zero(mem_ctx, struct nss_ctx);
     if (!nctx) {
         DEBUG(0, ("fatal error initializing nss_ctx\n"));
diff --git a/server/responder/nss/nsssrv.h b/server/responder/nss/nsssrv.h
index 093f795..37d3735 100644
--- a/server/responder/nss/nsssrv.h
+++ b/server/responder/nss/nsssrv.h
@@ -32,20 +32,14 @@
 #include "dbus/dbus.h"
 #include "sbus/sssd_dbus.h"
 #include "responder/common/responder_packet.h"
-#include "responder/common/responder_cmd.h"
+#include "responder/common/responder.h"
 #include "responder/nss/nsssrv_nc.h"
-#include <pcre.h>
 
 #define NSS_SBUS_SERVICE_VERSION 0x0001
 #define NSS_SBUS_SERVICE_NAME "nss"
 
 #define NSS_PACKET_MAX_RECV_SIZE 1024
 
-/* NSS_DOMAIN_DELIM can be specified in config.h */
-#ifndef NSS_DOMAIN_DELIM
-#define NSS_DOMAIN_DELIM '@'
-#endif
-
 #define NSS_ENUM_USERS 0x01
 #define NSS_ENUM_GROUPS 0x02
 #define NSS_ENUM_ALL 0x03
@@ -67,8 +61,6 @@ struct nss_ctx {
 
     struct getent_ctx *pctx;
     struct getent_ctx *gctx;
-
-    pcre *parse_name_re;
 };
 
 struct nss_packet;
diff --git a/server/responder/nss/nsssrv_cmd.c b/server/responder/nss/nsssrv_cmd.c
index 26c51fa..d090b9d 100644
--- a/server/responder/nss/nsssrv_cmd.c
+++ b/server/responder/nss/nsssrv_cmd.c
@@ -27,7 +27,7 @@
 
 struct nss_cmd_ctx {
     struct cli_ctx *cctx;
-    const char *name;
+    char *name;
     uint32_t id;
 
     bool immediate;
@@ -79,77 +79,6 @@ static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
     return; \
 } while(0)
 
-int nss_parse_name(TALLOC_CTX *memctx,
-                   struct nss_ctx *nctx,
-                   const char *origname,
-                   const char **domain, const char **name)
-{
-    pcre *re = nctx->parse_name_re;
-    const char *errstr;
-    const char *pattern = "(?<name>[^ ]+)@?(?<domain>[^ ]*$)";
-    const char *result;
-    int options;
-    int errpos;
-    int errval;
-    int ovec[30];
-    int origlen;
-    int ret, strnum;
-
-    options = PCRE_DUPNAMES | PCRE_EXTENDED;
-
-    if (!re) {
-        re = pcre_compile2(pattern, options, &errval, &errstr, &errpos, NULL);
-        if (!re) {
-            DEBUG(1, ("Invalid Regular Expression pattern at position %d. (%d [%s])\n",
-                      errpos, errstr));
-            return EFAULT;
-        }
-    }
-    nctx->parse_name_re = re;
-
-    origlen = strlen(origname);
-    options = PCRE_NOTEMPTY;
-
-    ret = pcre_exec(re, NULL, origname, origlen, 0, options, ovec, 30);
-    if (ret < 0) {
-        DEBUG(2, ("PCRE Matching error, %d\n", ret));
-        return EINVAL;
-    }
-
-    if (ret == 0) {
-        DEBUG(1, ("Too many matches, the pattern is invalid.\n"));
-    }
-
-    strnum = ret;
-
-    result = NULL;
-    ret = pcre_get_named_substring(re, origname, ovec, strnum, "name", &result);
-    if (ret < 0  || !result) {
-        DEBUG(2, ("Name not found!\n"));
-        return EINVAL;
-    }
-    *name = talloc_steal(memctx, result);
-    if (!*name) return ENOMEM;
-
-
-    result = NULL;
-    ret = pcre_get_named_substring(re, origname, ovec, strnum, "domain", &result);
-    if (ret < 0  || !result) {
-        DEBUG(4, ("Domain not provided!\n"));
-        *domain = NULL;
-    } else {
-        /* ignore "" string */
-        if (*result) {
-            *domain = talloc_steal(memctx, result);
-            if (!*domain) return ENOMEM;
-        } else {
-            *domain = NULL;
-        }
-    }
-
-    return EOK;
-}
-
 static int nss_dom_ctx_init(struct nss_dom_ctx *dctx,
                             struct btreemap *domain_map, const char *domain)
 {
@@ -189,12 +118,14 @@ static int fill_pwent(struct sss_packet *packet,
     size_t rsize, rp, blen;
     size_t s1, s2, s3, s4;
     size_t dom_len = 0;
-    int i, ret, num;
+    int delim = 1;
+    int i, ret, num, t;
     bool add_domain = info->fqnames;
     const char *domain = info->name;
+    const char *namefmt = nctx->rctx->names->fq_fmt;
     int ncret;
 
-    if (add_domain) dom_len = strlen(domain) +1;
+    if (add_domain) dom_len = strlen(domain);
 
     /* first 2 fields (len and reserved), filled up later */
     ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
@@ -245,8 +176,9 @@ static int fill_pwent(struct sss_packet *packet,
         s2 = strlen(gecos) + 1;
         s3 = strlen(homedir) + 1;
         s4 = strlen(shell) + 1;
+        if (add_domain) s1 += delim + dom_len;
+
         rsize = 2*sizeof(uint32_t) +s1 + 2 + s2 + s3 +s4;
-        if (add_domain) rsize += dom_len;
 
         ret = sss_packet_grow(packet, rsize);
         if (ret != EOK) {
@@ -258,13 +190,35 @@ static int fill_pwent(struct sss_packet *packet,
         ((uint32_t *)(&body[rp]))[0] = uid;
         ((uint32_t *)(&body[rp]))[1] = gid;
         rp += 2*sizeof(uint32_t);
-        memcpy(&body[rp], name, s1);
-        rp += s1;
+
         if (add_domain) {
-            body[rp-1] = NSS_DOMAIN_DELIM;
-            memcpy(&body[rp], domain, dom_len);
-            rp += dom_len;
+            ret = snprintf(&body[rp], s1, namefmt, name, domain);
+            if (ret >= s1) {
+                /* need more space, got creative with the print format ? */
+                t = ret - s1 + 1;
+                ret = sss_packet_grow(packet, t);
+                if (ret != EOK) {
+                    num = 0;
+                    goto done;
+                }
+                delim += t;
+                s1 += t;
+                sss_packet_get_body(packet, &body, &blen);
+
+                /* retry */
+                ret = snprintf(&body[rp], s1, namefmt, name, domain);
+            }
+
+            if (ret != s1-1) {
+                DEBUG(1, ("Failed to generate a fully qualified name for user "
+                          "[%s] in [%s]! Skipping user.\n", name, domain));
+                continue;
+            }
+        } else {
+            memcpy(&body[rp], name, s1);
         }
+        rp += s1;
+
         memcpy(&body[rp], "x", 2);
         rp += 2;
         memcpy(&body[rp], gecos, s2);
@@ -493,8 +447,8 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
     struct sss_domain_info *info;
     struct nss_ctx *nctx;
     const char **domains;
-    const char *domname;
     const char *rawname;
+    char *domname;
     uint8_t *body;
     size_t blen;
     int ret, num, i;
@@ -519,7 +473,7 @@ static int nss_cmd_getpwnam(struct cli_ctx *cctx)
     rawname = (const char *)body;
 
     domname = NULL;
-    ret = nss_parse_name(cmdctx, nctx, rawname,
+    ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
                          &domname, &cmdctx->name);
     if (ret != EOK) {
         DEBUG(2, ("Invalid name received [%s]\n", rawname));
@@ -1332,16 +1286,18 @@ static int fill_grent(struct sss_packet *packet,
     const char *name;
     uint32_t gid, uid;
     size_t rsize, rp, blen, mnump;
-    int i, j, n, ret, num, memnum;
+    int i, j, n, t, ret, num, memnum;
     bool get_members;
     bool skip_members;
     size_t dom_len = 0;
     size_t name_len;
+    int delim = 1;
     bool add_domain = info->fqnames;
     const char *domain = info->name;
+    const char *namefmt = nctx->rctx->names->fq_fmt;
     int ncret;
 
-    if (add_domain) dom_len = strlen(domain) +1;
+    if (add_domain) dom_len = strlen(domain);
 
     /* first 2 fields (len and reserved), filled up later */
     ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
@@ -1396,11 +1352,15 @@ static int fill_grent(struct sss_packet *packet,
             }
 
             /* fill in gid and name and set pointer for number of members */
-            name_len = strlen(name)+1;
-            rsize = 2 * sizeof(uint32_t) + name_len +2;
-            if (add_domain) rsize += dom_len;
+            name_len = strlen(name) + 1;
+            if (add_domain) name_len += delim + dom_len;
+            rsize = 2 * sizeof(uint32_t) + name_len + 2;
 
             ret = sss_packet_grow(packet, rsize);
+            if (ret != EOK) {
+                num = 0;
+                goto done;
+            }
             sss_packet_get_body(packet, &body, &blen);
 
             /*  0-3: 64bit number gid */
@@ -1414,13 +1374,34 @@ static int fill_grent(struct sss_packet *packet,
             rp += sizeof(uint32_t);
 
             /*  8-X: sequence of strings (name, passwd, mem..) */
-            memcpy(&body[rp], name, name_len);
-            rp += name_len;
             if (add_domain) {
-                body[rp-1] = NSS_DOMAIN_DELIM;
-                memcpy(&body[rp], domain, dom_len);
-                rp += dom_len;
+                ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                if (ret >= name_len) {
+                    /* need more space, got creative with the print format ? */
+                    t = ret - name_len + 1;
+                    ret = sss_packet_grow(packet, t);
+                    if (ret != EOK) {
+                        num = 0;
+                        goto done;
+                    }
+                    delim += t;
+                    name_len += t;
+                    sss_packet_get_body(packet, &body, &blen);
+
+                    /* retry */
+                    ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                }
+
+                if (ret != name_len-1) {
+                    DEBUG(1, ("Failed to generate a fully qualified name for user "
+                              "[%s] in [%s]! Skipping user.\n", name, domain));
+                    continue;
+                }
+            } else {
+                memcpy(&body[rp], name, name_len);
             }
+            rp += name_len;
+
             body[rp] = 'x'; /* group passwd field */
             body[rp+1] = '\0';
 
@@ -1435,20 +1416,21 @@ static int fill_grent(struct sss_packet *packet,
                 n = 0;
                 for (j = 0; j < memnum; j++) {
 
+                    name = (char *)el->values[j].data;
+
                     ncret = nss_ncache_check_user(nctx->ncache,
-                                                nctx->neg_timeout, domain,
-                                                (char *)el->values[j].data);
+                                                  nctx->neg_timeout,
+                                                  domain, name);
                     if (ncret == EEXIST) {
                         DEBUG(4, ("User [%s %s] filtered out! (negative cache)\n",
                                   name, domain));
                         continue;
                     }
 
-                    rsize = el->values[j].length + 1;
-                    if (add_domain) {
-                        name_len = rsize;
-                        rsize += dom_len;
-                    }
+                    name_len = el->values[j].length + 1;
+                    if (add_domain) name_len += delim + dom_len;
+
+                    rsize = name_len;
                     ret = sss_packet_grow(packet, rsize);
                     if (ret != EOK) {
                         num = 0;
@@ -1457,12 +1439,34 @@ static int fill_grent(struct sss_packet *packet,
 
                     sss_packet_get_body(packet, &body, &blen);
                     rp = blen - rsize;
-                    memcpy(&body[rp], el->values[j].data, el->values[j].length);
+
                     if (add_domain) {
-                        rp += name_len;
-                        body[rp-1] = NSS_DOMAIN_DELIM;
-                        memcpy(&body[rp], domain, dom_len);
+                        ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                        if (ret >= name_len) {
+                            /* need more space, got creative with the print format ? */
+                            t = ret - name_len + 1;
+                            ret = sss_packet_grow(packet, t);
+                            if (ret != EOK) {
+                                num = 0;
+                                goto done;
+                            }
+                            delim += t;
+                            name_len += t;
+                            sss_packet_get_body(packet, &body, &blen);
+
+                            /* retry */
+                            ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                        }
+
+                        if (ret != name_len-1) {
+                            DEBUG(1, ("Failed to generate a fully qualified name for user "
+                                      "[%s] in [%s]! Skipping user.\n", name, domain));
+                            continue;
+                        }
+                    } else {
+                        memcpy(&body[rp], name, name_len);
                     }
+                    rp += name_len;
                     body[blen-1] = '\0';
 
                     n++;
@@ -1514,12 +1518,10 @@ static int fill_grent(struct sss_packet *packet,
                 continue;
             }
 
-            rsize = strlen(name) + 1;
-            if (add_domain) {
-                name_len = rsize;
-                rsize += dom_len;
-            }
+            name_len = strlen(name) + 1;
+            if (add_domain) name_len += delim + dom_len;
 
+            rsize = name_len;
             ret = sss_packet_grow(packet, rsize);
             if (ret != EOK) {
                 num = 0;
@@ -1527,13 +1529,34 @@ static int fill_grent(struct sss_packet *packet,
             }
             sss_packet_get_body(packet, &body, &blen);
             rp = blen - rsize;
-            memcpy(&body[rp], name, rsize);
+
             if (add_domain) {
-                body[rp-1] = NSS_DOMAIN_DELIM;
-                memcpy(&body[rp], domain, dom_len);
-                rp += dom_len;
-            }
+                ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                if (ret >= name_len) {
+                    /* need more space, got creative with the print format ? */
+                    t = ret - name_len + 1;
+                    ret = sss_packet_grow(packet, t);
+                    if (ret != EOK) {
+                        num = 0;
+                        goto done;
+                    }
+                    delim += t;
+                    name_len += t;
+                    sss_packet_get_body(packet, &body, &blen);
+
+                    /* retry */
+                    ret = snprintf(&body[rp], name_len, namefmt, name, domain);
+                }
 
+                if (ret != name_len-1) {
+                    DEBUG(1, ("Failed to generate a fully qualified name for user "
+                              "[%s] in [%s]! Skipping user.\n", name, domain));
+                    continue;
+                }
+            } else {
+                memcpy(&body[rp], name, name_len);
+            }
+            rp += name_len;
             memnum++;
 
             continue;
@@ -1752,8 +1775,8 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
     struct sss_domain_info *info;
     struct nss_ctx *nctx;
     const char **domains;
-    const char *domname;
     const char *rawname;
+    char *domname;
     uint8_t *body;
     size_t blen;
     int ret, num, i;
@@ -1777,7 +1800,7 @@ static int nss_cmd_getgrnam(struct cli_ctx *cctx)
     rawname = (const char *)body;
 
     domname = NULL;
-    ret = nss_parse_name(cmdctx, nctx, rawname,
+    ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
                          &domname, &cmdctx->name);
     if (ret != EOK) {
         DEBUG(2, ("Invalid name received [%s]\n", rawname));
@@ -2844,8 +2867,8 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
     struct sss_domain_info *info;
     struct nss_ctx *nctx;
     const char **domains;
-    const char *domname;
     const char *rawname;
+    char *domname;
     uint8_t *body;
     size_t blen;
     int ret, num, i;
@@ -2869,7 +2892,7 @@ static int nss_cmd_initgroups(struct cli_ctx *cctx)
     rawname = (const char *)body;
 
     domname = NULL;
-    ret = nss_parse_name(cmdctx, nctx, rawname,
+    ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
                          &domname, &cmdctx->name);
     if (ret != EOK) {
         DEBUG(2, ("Invalid name received [%s]\n", rawname));
diff --git a/server/responder/pam/pamsrv.c b/server/responder/pam/pamsrv.c
index d653a00..2f74a4a 100644
--- a/server/responder/pam/pamsrv.c
+++ b/server/responder/pam/pamsrv.c
@@ -37,8 +37,6 @@
 #include "sbus/sssd_dbus.h"
 #include "util/btreemap.h"
 #include "responder/common/responder_packet.h"
-#include "responder/common/responder_cmd.h"
-#include "responder/common/responder_common.h"
 #include "providers/data_provider.h"
 #include "monitor/monitor_sbus.h"
 #include "monitor/monitor_interfaces.h"
diff --git a/server/responder/pam/pamsrv.h b/server/responder/pam/pamsrv.h
index ac29cb1..077b495 100644
--- a/server/responder/pam/pamsrv.h
+++ b/server/responder/pam/pamsrv.h
@@ -4,7 +4,7 @@
 
 #include "util/util.h"
 #include "sbus/sssd_dbus.h"
-#include "responder/common/responder_cmd.h"
+#include "responder/common/responder.h"
 
 #define PAM_DP_TIMEOUT 5000
 
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 69f198c..8f74e96 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -4,55 +4,55 @@
 #include "util/util.h"
 #include "confdb/confdb.h"
 #include "responder/pam/pam_LOCAL_domain.h"
-#include "responder/common/responder_common.h"
-#include "responder/common/responder_cmd.h"
-#include "responder/common/responder_packet.h"
 #include "responder/pam/pamsrv.h"
 
-static int pam_parse_in_data(uint8_t *body, size_t blen, struct pam_data *pd) {
+static int pam_parse_in_data(struct sss_names_ctx *snctx,
+                             struct pam_data *pd,
+                             uint8_t *body, size_t blen)
+{
     int start;
     int end;
-    int last=blen-1;
-    char *delim;
+    int last;
+    int ret;
 
-    start = end = 0;
-    while ( end < last && body[end++]!='\0');
-    pd->user = (char *) &body[start];
+    last = blen - 1;
+    end = 0;
 
-    delim = strchr(pd->user, SSS_DOMAIN_DELIM);
-    if (delim != NULL ) {
-        *delim = '\0';
-        pd->domain = delim+1;
-    } else {
-        pd->domain =  NULL;
-    }
+    /* user name */
+    for (start = end; end < last; end++) if (body[end] == '\0') break;
+    if (body[end++] != '\0') return EINVAL;
 
-    start = end;
-    while ( end < last && body[end++]!='\0');
+    ret = sss_parse_name(pd, snctx, &body[start], &pd->domain, &pd->user);
+    if (ret != EOK) return ret;
+
+    for (start = end; end < last; end++) if (body[end] == '\0') break;
+    if (body[end++] != '\0') return EINVAL;
     pd->service = (char *) &body[start];
 
-    start = end;
-    while ( end < last && body[end++]!='\0');
+    for (start = end; end < last; end++) if (body[end] == '\0') break;
+    if (body[end++] != '\0') return EINVAL;
     pd->tty = (char *) &body[start];
 
-    start = end;
-    while ( end < last && body[end++]!='\0');
+    for (start = end; end < last; end++) if (body[end] == '\0') break;
+    if (body[end++] != '\0') return EINVAL;
     pd->ruser = (char *) &body[start];
 
-    start = end;
-    while ( end < last && body[end++]!='\0');
+    for (start = end; end < last; end++) if (body[end] == '\0') break;
+    if (body[end++] != '\0') return EINVAL;
     pd->rhost = (char *) &body[start];
 
     start = end;
     pd->authtok_type = (int) body[start];
+
     start += sizeof(uint32_t);
     pd->authtok_size = (int) body[start];
+
     start += sizeof(uint32_t);
-    end =  start+pd->authtok_size;
-    if ( pd->authtok_size == 0 ) {
+    end = start + pd->authtok_size;
+    if (pd->authtok_size == 0) {
         pd->authtok = NULL;
     } else {
-        if ( end <= blen ) {
+        if (end <= blen) {
             pd->authtok = (uint8_t *) &body[start];
         } else {
             DEBUG(1, ("Invalid authtok size: %d\n", pd->authtok_size));
@@ -62,14 +62,17 @@ static int pam_parse_in_data(uint8_t *body, size_t blen, struct pam_data *pd) {
 
     start = end;
     pd->newauthtok_type = (int) body[start];
+
     start += sizeof(uint32_t);
     pd->newauthtok_size = (int) body[start];
+
     start += sizeof(uint32_t);
-    end =  start+pd->newauthtok_size;
-    if ( pd->newauthtok_size == 0 ) {
+    end = start + pd->newauthtok_size;
+
+    if (pd->newauthtok_size == 0) {
         pd->newauthtok = NULL;
     } else {
-        if ( end <= blen ) {
+        if (end <= blen) {
             pd->newauthtok = (uint8_t *) &body[start];
         } else {
             DEBUG(1, ("Invalid newauthtok size: %d\n", pd->newauthtok_size));
@@ -213,7 +216,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd)
 
     pd->cmd = pam_cmd;
     pd->cctx = cctx;
-    ret=pam_parse_in_data(body, blen, pd);
+    ret=pam_parse_in_data(cctx->rctx->names, pd, body, blen);
     if( ret != 0 ) {
         talloc_free(pd);
         return EINVAL;
-- 
1.6.0.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]