[Freeipa-devel] [PATCHES] added chpass target to proxy and LDAP backend

Sumit Bose sbose at redhat.com
Tue Jul 21 16:58:58 UTC 2009


On Tue, Jul 21, 2009 at 05:56:27PM +0200, Sumit Bose wrote:
> On Tue, Jul 21, 2009 at 02:45:39PM +0200, Sumit Bose wrote:
> > Hi,
> > 
> > the included patches will add the chpass target to the proxy and LDAP
> > backend (one of them will add the access target to then proxy backend,
> > too). While the proxy targets are simply calls to the old pam handler,
> > the LDAP chpass target uses the latest scheme pushed by Simo yesterday.
> > Simo can you please check if I got it right?
> > 
> 
> In response to a discussion on irc I've made to following changes:
> 
> - auth_recv and auth4chpass_recv are united into auth_recv
> - remove BER stuff from the state structure and make sure is it freed
>   after use
> - init state->result with NULL.
> 

removed the memctx == NULL check.

bye,
Sumit
-------------- next part --------------
>From 5e8ed566296d5390d51def73f041c9bd9f510995 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 16 Jul 2009 16:40:29 +0200
Subject: [PATCH 1/2] add handling of the new backend targets to proxy backend

---
 server/providers/proxy.c |   30 ++++++++++++++++++++++++++++++
 1 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/server/providers/proxy.c b/server/providers/proxy.c
index aa5b1c9..ddfbe39 100644
--- a/server/providers/proxy.c
+++ b/server/providers/proxy.c
@@ -2069,6 +2069,18 @@ struct bet_ops proxy_auth_ops = {
     .finalize = proxy_auth_shutdown
 };
 
+struct bet_ops proxy_access_ops = {
+    .check_online = proxy_check_online,
+    .handler = proxy_pam_handler,
+    .finalize = proxy_auth_shutdown
+};
+
+struct bet_ops proxy_chpass_ops = {
+    .check_online = proxy_check_online,
+    .handler = proxy_pam_handler,
+    .finalize = proxy_auth_shutdown
+};
+
 static void *proxy_dlsym(void *handle, const char *functemp, char *libname)
 {
     char *funcname;
@@ -2238,3 +2250,21 @@ done:
     }
     return ret;
 }
+
+int sssm_proxy_access_init(struct be_ctx *bectx,
+                           struct bet_ops **ops, void **pvt_data)
+{
+    int ret;
+    ret = sssm_proxy_auth_init(bectx, ops, pvt_data);
+    *ops = &proxy_access_ops;
+    return ret;
+}
+
+int sssm_proxy_chpass_init(struct be_ctx *bectx,
+                           struct bet_ops **ops, void **pvt_data)
+{
+    int ret;
+    ret = sssm_proxy_auth_init(bectx, ops, pvt_data);
+    *ops = &proxy_chpass_ops;
+    return ret;
+}
-- 
1.6.2.5

-------------- next part --------------
>From fb6ca1baf3a302f2629560f2c0ec1ab30159a69c Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 20 Jul 2009 17:27:02 +0200
Subject: [PATCH 2/2] added LDAP change password backend target

---
 server/providers/data_provider_be.c |    8 ++-
 server/providers/ldap/ldap_auth.c   |  161 ++++++++++++++++++++++++++++++++++-
 server/providers/ldap/sdap_async.c  |  134 +++++++++++++++++++++++++++++
 server/providers/ldap/sdap_async.h  |    8 ++
 4 files changed, 307 insertions(+), 4 deletions(-)

diff --git a/server/providers/data_provider_be.c b/server/providers/data_provider_be.c
index 5cd5994..2e0c1cf 100644
--- a/server/providers/data_provider_be.c
+++ b/server/providers/data_provider_be.c
@@ -631,8 +631,10 @@ static int be_pam_handler(DBusMessage *message, struct sbus_conn_ctx *sconn)
     }
 
     be_req = talloc_zero(ctx, struct be_req);
-    if (!be_req)
+    if (!be_req) {
+        DEBUG(7, ("talloc_zero failed.\n"));
         goto done;
+    }
 
     be_req->be_ctx = ctx;
     be_req->fn = be_pam_handler_callback;
@@ -640,8 +642,10 @@ static int be_pam_handler(DBusMessage *message, struct sbus_conn_ctx *sconn)
     be_req->req_data = pd;
 
     ret = be_file_request(ctx, ctx->bet_info[target].bet_ops->handler, be_req);
-    if (ret != EOK)
+    if (ret != EOK) {
+        DEBUG(7, ("be_file_request failed.\n"));
         goto done;
+    }
 
     return EOK;
 
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index 2c53032..f0b12a0 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -283,7 +283,8 @@ static void auth_bind_user_done(struct tevent_req *subreq)
     tevent_req_done(req);
 }
 
-int auth_recv(struct tevent_req *req, enum sdap_result *result)
+int auth_recv(struct tevent_req *req, enum sdap_result *result,
+                     TALLOC_CTX *memctx, struct sdap_handle **sh, char **dn)
 {
     struct auth_state *state = tevent_req_data(req,
                                                     struct auth_state);
@@ -296,11 +297,151 @@ int auth_recv(struct tevent_req *req, enum sdap_result *result)
         return EOK;
     }
 
+    if (sh != NULL) {
+        *sh = talloc_steal(memctx, state->sh);
+        if (*sh == NULL) return ENOMEM;
+    }
+
+    if (dn != NULL) {
+        *dn = talloc_steal(memctx, state->dn);
+        if (*dn == NULL) return ENOMEM;
+    }
+
     *result = state->result;
     return EOK;
 }
 
+/* ==Perform-Password-Change===================== */
+
+struct sdap_pam_chpass_state {
+    struct be_req *breq;
+    struct pam_data *pd;
+    const char *username;
+    char *dn;
+    char *password;
+    char *new_password;
+    struct sdap_handle *sh;
+};
 
+static void sdap_auth4chpass_done(struct tevent_req *req);
+static void sdap_pam_chpass_done(struct tevent_req *req);
+static void sdap_pam_auth_reply(struct be_req *breq, int result);
+
+static void sdap_pam_chpass_send(struct be_req *breq)
+{
+    struct sdap_pam_chpass_state *state;
+    struct sdap_auth_ctx *ctx;
+    struct tevent_req *subreq;
+    struct pam_data *pd;
+
+    ctx = talloc_get_type(breq->be_ctx->bet_info[BET_CHPASS].pvt_bet_data,
+                          struct sdap_auth_ctx);
+    pd = talloc_get_type(breq->req_data, struct pam_data);
+
+    DEBUG(2, ("starting password change request for user [%s].\n", pd->user));
+
+    pd->pam_status = PAM_SYSTEM_ERR;
+
+    if (pd->cmd != SSS_PAM_CHAUTHTOK) {
+        DEBUG(2, ("chpass target was called by wrong pam command.\n"));
+        goto done;
+    }
+
+    state = talloc_zero(breq, struct sdap_pam_chpass_state);
+    if (!state) goto done;
+
+    state->breq = breq;
+    state->pd = pd;
+    state->username = pd->user;
+    state->password = talloc_strndup(state,
+                                     (char *)pd->authtok, pd->authtok_size);
+    if (!state->password) goto done;
+    talloc_set_destructor((TALLOC_CTX *)state->password,
+                          password_destructor);
+    state->new_password = talloc_strndup(state,
+                                         (char *)pd->newauthtok,
+                                         pd->newauthtok_size);
+    if (!state->new_password) goto done;
+    talloc_set_destructor((TALLOC_CTX *)state->new_password,
+                          password_destructor);
+
+    subreq = auth_send(breq, breq->be_ctx->ev,
+                       ctx, state->username, state->password);
+    if (!subreq) goto done;
+
+    tevent_req_set_callback(subreq, sdap_auth4chpass_done, state);
+    return;
+done:
+    sdap_pam_auth_reply(breq, pd->pam_status);
+}
+
+static void sdap_auth4chpass_done(struct tevent_req *req)
+{
+    struct sdap_pam_chpass_state *state =
+                    tevent_req_callback_data(req, struct sdap_pam_chpass_state);
+    struct tevent_req *subreq;
+    enum sdap_result result;
+    int ret;
+
+    ret = auth_recv(req, &result, state, &state->sh, &state->dn);
+    talloc_zfree(req);
+    if (ret) {
+        state->pd->pam_status = PAM_SYSTEM_ERR;
+        goto done;
+    }
+
+
+    switch (result) {
+    case SDAP_AUTH_SUCCESS:
+        DEBUG(7, ("user [%s] successfully authenticated.\n", state->dn));
+        subreq = sdap_exop_modify_passwd_send(state,
+                                              state->breq->be_ctx->ev,
+                                              state->sh,
+                                              state->dn,
+                                              state->password,
+                                              state->new_password);
+
+        if (!subreq) {
+            DEBUG(2, ("Failed to change password for %s\n", state->username));
+            goto done;
+        }
+
+        tevent_req_set_callback(subreq, sdap_pam_chpass_done, state);
+        return;
+        break;
+    default:
+        state->pd->pam_status = PAM_SYSTEM_ERR;
+    }
+
+done:
+    sdap_pam_auth_reply(state->breq, state->pd->pam_status);
+}
+
+static void sdap_pam_chpass_done(struct tevent_req *req)
+{
+    struct sdap_pam_chpass_state *state =
+                    tevent_req_callback_data(req, struct sdap_pam_chpass_state);
+    enum sdap_result result;
+    int ret;
+
+    ret = sdap_exop_modify_passwd_recv(req, &result);
+    talloc_zfree(req);
+    if (ret) {
+        state->pd->pam_status = PAM_SYSTEM_ERR;
+        goto done;
+    }
+
+    switch (result) {
+    case SDAP_SUCCESS:
+        state->pd->pam_status = PAM_SUCCESS;
+        break;
+    default:
+        state->pd->pam_status = PAM_SYSTEM_ERR;
+    }
+
+done:
+    sdap_pam_auth_reply(state->breq, state->pd->pam_status);
+}
 /* ==Perform-User-Authentication-and-Password-Caching===================== */
 
 struct sdap_pam_auth_state {
@@ -369,7 +510,7 @@ static void sdap_pam_auth_done(struct tevent_req *req)
     enum sdap_result result;
     int ret;
 
-    ret = auth_recv(req, &result);
+    ret = auth_recv(req, &result, NULL, NULL, NULL);
     talloc_zfree(req);
     if (ret) {
         state->pd->pam_status = PAM_SYSTEM_ERR;
@@ -453,6 +594,12 @@ struct bet_ops sdap_auth_ops = {
     .finalize = sdap_shutdown
 };
 
+struct bet_ops sdap_chpass_ops = {
+    .check_online = NULL,
+    .handler = sdap_pam_chpass_send,
+    .finalize = sdap_shutdown
+};
+
 int sssm_ldap_auth_init(struct be_ctx *bectx,
                         struct bet_ops **ops,
                         void **pvt_data)
@@ -514,3 +661,13 @@ done:
     }
     return ret;
 }
+
+int sssm_ldap_chpass_init(struct be_ctx *bectx,
+                          struct bet_ops **ops,
+                          void **pvt_data)
+{
+    int ret;
+    ret = sssm_ldap_auth_init(bectx, ops, pvt_data);
+    *ops = &sdap_chpass_ops;
+    return ret;
+}
diff --git a/server/providers/ldap/sdap_async.c b/server/providers/ldap/sdap_async.c
index 57234e3..d5e42f0 100644
--- a/server/providers/ldap/sdap_async.c
+++ b/server/providers/ldap/sdap_async.c
@@ -1639,3 +1639,137 @@ int sdap_get_initgr_recv(struct tevent_req *req)
     return EOK;
 }
 
+struct sdap_exop_modify_passwd_state {
+    struct sdap_handle *sh;
+    int msgid;
+    char *user_dn;
+    char *password;
+    char *new_password;
+    int result;
+    struct sdap_msg *reply;
+};
+
+static void sdap_exop_modify_passwd_done(void *pvt, int error, struct sdap_msg *reply);
+
+struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
+                                           struct tevent_context *ev,
+                                           struct sdap_handle *sh,
+                                           char *user_dn,
+                                           char *password,
+                                           char *new_password)
+{
+    struct tevent_req *req = NULL;
+    struct sdap_exop_modify_passwd_state *state;
+    int ret;
+    BerElement *ber = NULL;
+    struct berval *bv = NULL;
+
+    req = tevent_req_create(memctx, &state,
+                            struct sdap_exop_modify_passwd_state);
+    if (!req) return NULL;
+
+    state->sh = sh;
+    state->reply = NULL;
+
+    ber = ber_alloc_t( LBER_USE_DER );
+    if (ber == NULL) {
+        DEBUG(7, ("ber_alloc_t failed.\n"));
+        talloc_zfree(req);
+        return NULL;
+    }
+
+    ret = ber_printf( ber, "{tststs}", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
+                     user_dn,
+                     LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, password,
+                     LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, new_password);
+    if (ret == -1) {
+        DEBUG(1, ("ber_printf failed.\n"));
+        ber_free(ber, 1);
+        talloc_zfree(req);
+        return NULL;
+    }
+
+    ret = ber_flatten(ber, &bv);
+    ber_free(ber, 1);
+    if (ret == -1) {
+        DEBUG(1, ("ber_flatten failed.\n"));
+        talloc_zfree(req);
+        return NULL;
+    }
+
+    DEBUG(4, ("Executing extended operation\n"));
+
+    ret = ldap_extended_operation(state->sh->ldap, LDAP_EXOP_MODIFY_PASSWD,
+                                  bv, NULL, NULL, &state->msgid);
+    ber_bvfree(bv);
+    if (ret == -1 || state->msgid == -1) {
+        DEBUG(1, ("ldap_extended_operation failed\n"));
+        goto fail;
+    }
+    DEBUG(8, ("ldap_extended_operation sent, msgid = %d\n", state->msgid));
+
+    /* FIXME: get timeouts from configuration, for now 5 secs. */
+    ret = sdap_op_add(state, ev, state->sh, state->msgid,
+                      sdap_exop_modify_passwd_done, req, 5);
+    if (ret) {
+        DEBUG(1, ("Failed to set up operation!\n"));
+        goto fail;
+    }
+
+    return req;
+
+fail:
+    tevent_req_error(req, EIO);
+    tevent_req_post(req, ev);
+    return req;
+}
+
+static void sdap_exop_modify_passwd_done(void *pvt, int error, struct sdap_msg *reply)
+{
+    struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
+    struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
+                                         struct sdap_exop_modify_passwd_state);
+    char *errmsg;
+    int ret;
+
+    if (error) {
+        tevent_req_error(req, error);
+        return;
+    }
+
+    state->reply = talloc_steal(state, reply);
+
+    ret = ldap_parse_result(state->sh->ldap, state->reply->msg,
+                            &state->result, NULL, &errmsg, NULL, NULL, 0);
+    if (ret != LDAP_SUCCESS) {
+        DEBUG(2, ("ldap_parse_result failed (%d)\n", state->msgid));
+        tevent_req_error(req, EIO);
+        return;
+    }
+
+    DEBUG(3, ("ldap_extended_operation result: %s(%d), %s\n",
+              ldap_err2string(state->result), state->result, errmsg));
+
+    tevent_req_done(req);
+}
+
+int sdap_exop_modify_passwd_recv(struct tevent_req *req,
+                                 enum sdap_result *result)
+{
+    struct sdap_exop_modify_passwd_state *state = tevent_req_data(req,
+                                         struct sdap_exop_modify_passwd_state);
+    enum tevent_req_state tstate;
+    uint64_t err;
+
+    *result = SDAP_ERROR;
+
+    if (tevent_req_is_error(req, &tstate, &err)) {
+        return err;
+    }
+
+    if (state->result == LDAP_SUCCESS) {
+        *result = SDAP_SUCCESS;
+    }
+
+    return EOK;
+}
diff --git a/server/providers/ldap/sdap_async.h b/server/providers/ldap/sdap_async.h
index 6ed9532..4012729 100644
--- a/server/providers/ldap/sdap_async.h
+++ b/server/providers/ldap/sdap_async.h
@@ -85,3 +85,11 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
                                         const char *name,
                                         const char **grp_attrs);
 int sdap_get_initgr_recv(struct tevent_req *req);
+
+struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
+                                                struct tevent_context *ev,
+                                                struct sdap_handle *sh,
+                                                char *user_dn,
+                                                char *password,
+                                                char *new_password);
+int sdap_exop_modify_passwd_recv(struct tevent_req *req, enum sdap_result *result);
-- 
1.6.2.5



More information about the Freeipa-devel mailing list