ipa_s2n_exop.c revision 4cf3bc3b94ccf1e60d29c0eb765f02cb49fbac2d
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose IPA Helper routines - external users and groups with s2n plugin
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose Copyright (C) Sumit Bose <sbose@redhat.com> - 2011
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose This program is free software; you can redistribute it and/or modify
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose it under the terms of the GNU General Public License as published by
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose the Free Software Foundation; either version 3 of the License, or
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose (at your option) any later version.
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose This program is distributed in the hope that it will be useful,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose but WITHOUT ANY WARRANTY; without even the implied warranty of
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose GNU General Public License for more details.
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose You should have received a copy of the GNU General Public License
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose along with this program. If not, see <http://www.gnu.org/licenses/>.
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose/* ==Sid2Name Extended Operation============================================= */
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose#define EXOP_SID2NAME_OID "2.16.840.1.113730.3.8.10.4"
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic struct tevent_req *ipa_s2n_exop_send(TALLOC_CTX *mem_ctx,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_exop_state);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_TRACE_FUNC, ("Executing extended operation\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ldap_extended_operation(state->sh->ldap, EXOP_SID2NAME_OID,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("ldap_extended_operation failed\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_TRACE_INTERNAL, ("ldap_extended_operation sent, msgid = %d\n", msgid));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose /* FIXME: get timeouts from configuration, for now 10 secs. */
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = sdap_op_add(state, ev, state->sh, msgid, ipa_s2n_exop_done, req, 10,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to set up operation!\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose struct tevent_req *req = talloc_get_type(pvt, struct tevent_req);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose struct ipa_s2n_exop_state *state = tevent_req_data(req,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ldap_parse_result(state->sh->ldap, reply->msg,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ldap_parse_result failed (%d)\n", state->op->msgid));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_TRACE_FUNC, ("ldap_extended_operation result: %s(%d), %s\n",
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose sss_ldap_err2string(state->result), state->result, errmsg));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ldap_parse_extended_result(state->sh->ldap, reply->msg,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ldap_parse_extendend_result failed (%d)\n", ret));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose state->retdata->bv_val = talloc_memdup(state->retdata, retdata->bv_val,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_memdup failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic int ipa_s2n_exop_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose struct ipa_s2n_exop_state *state = tevent_req_data(req,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose *retdata = talloc_steal(mem_ctx, state->retdata);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic errno_t talloc_ber_flatten(TALLOC_CTX *mem_ctx, BerElement *ber,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose tbv->bv_val = talloc_memdup(tbv, bv->bv_val, bv->bv_len);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose/* The extended operation expect the following ASN.1 encoded request data:
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * ExtdomRequestValue ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * inputType ENUMERATED {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * posix uid (3),
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * posix gid (3)
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * requestType ENUMERATED {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * simple (1),
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * data InputData
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * InputData ::= CHOICE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * sid OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * name NameDomainData
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * uid PosixUid,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * gid PosixGid
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * NameDomainData ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * object_name OCTET STRING
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * PosixUid ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * uid INTEGER
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * PosixGid ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * gid INTEGER
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic errno_t s2n_encode_request(TALLOC_CTX *mem_ctx,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose const char *name,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ber_printf(ber, "{ee{ss}}", INP_NAME, REQ_FULL,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ber_printf(ber, "{ee{si}}", INP_POSIX_UID, REQ_FULL,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ber_printf(ber, "{ee{ss}}", INP_NAME, REQ_FULL,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ber_printf(ber, "{ee{si}}", INP_POSIX_GID, REQ_FULL,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose/* If the extendend operation is successful it returns the following ASN.1
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * encoded response:
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * ExtdomResponseValue ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * responseType ENUMERATED {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * posix_user (3),
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * posix_group (4)
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * data OutputData
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * OutputData ::= CHOICE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * sid OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * name NameDomainData,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * user PosixUser,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * group PosixGroup
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * NameDomainData ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * object_name OCTET STRING
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * PosixUser ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * user_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * uid INTEGER
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * gid INTEGER
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * PosixGroup ::= SEQUENCE {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * group_name OCTET STRING,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * gid INTEGER
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * Since we always request the full data set (REQ_FULL), i.e user/group name,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * domain name and corresponding unix id, only PosixUser (RESP_USER) and
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose * PosixGroup (RESP_GROUP) are handled by s2n_response_to_attrs().
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic errno_t s2n_response_to_attrs(TALLOC_CTX *mem_ctx,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Missing OID or data.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ("Result has wrong OID, expected [%s], got [%s].\n",
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ber_init failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ber_scanf failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_zero failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose tag = ber_scanf(ber, "{aaii}}", &domain_name, &name, &uid, &gid);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ber_scanf failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose attrs->a.user.pw_name = talloc_strdup(attrs, name);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose tag = ber_scanf(ber, "{aai}}", &domain_name, &name, &gid);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ber_scanf failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose attrs->a.group.gr_name = talloc_strdup(attrs, name);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Unexpected response type [%d].\n",
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose attrs->domain_name = talloc_strdup(attrs, domain_name);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic void ipa_s2n_get_user_done(struct tevent_req *subreq);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestruct tevent_req *ipa_s2n_get_acct_info_send(TALLOC_CTX *mem_ctx,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose const char **attrs,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose const char *name,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose if ((name == NULL && id == 0) || (name != NULL && id != 0)) {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Either a user name or a uid expected, "
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose "not both or nothing.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose req = tevent_req_create(mem_ctx, &state, struct ipa_s2n_get_user_state);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = s2n_encode_request(state, dom->name, entry_type, name, id, &bv_req);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose subreq = ipa_s2n_exop_send(state, state->ev, state->sh, bv_req);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("ipa_s2n_exop_send failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose tevent_req_set_callback(subreq, ipa_s2n_get_user_done, req);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bosestatic void ipa_s2n_get_user_done(struct tevent_req *subreq)
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose struct tevent_req *req = tevent_req_callback_data(subreq,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose struct ipa_s2n_get_user_state *state = tevent_req_data(req,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose uint64_t timeout = 10*60*60; /* FIXME: find a better timeout ! */
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = ipa_s2n_exop_recv(subreq, state, &result, &retoid, &retdata);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("s2n exop request failed.\n"));
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = s2n_response_to_attrs(state, retoid, retdata, &attrs);
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("s2n_response_to_attrs failed.\n"));
70eaade10feedd7845e39170d0b7eebf3a030af1Sumit Bose if (!(strcasecmp(state->dom->name, attrs->domain_name) == 0 ||
70eaade10feedd7845e39170d0b7eebf3a030af1Sumit Bose strcasecmp(state->dom->flat_name, attrs->domain_name) == 0))) {
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Unexpected domain name returned, "
70eaade10feedd7845e39170d0b7eebf3a030af1Sumit Bose "expected [%s] or [%s], got [%s].\n",
70eaade10feedd7845e39170d0b7eebf3a030af1Sumit Bose state->dom->flat_name == NULL ? "" : state->dom->flat_name,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = sysdb_store_domuser(state->dom, attrs->a.user.pw_name, NULL,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose ret = sysdb_store_domgroup(state->dom, attrs->a.group.gr_name,
36a12aea020a935ffa40505fa02860c3d921ad0cSumit Bose DEBUG(SSSDBG_OP_FAILURE, ("Unexpected response type [%d].\n",