2011-11-30 06:29:10 -06:00
|
|
|
/** BEGIN COPYRIGHT BLOCK
|
|
|
|
* 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/>.
|
|
|
|
*
|
|
|
|
* Additional permission under GPLv3 section 7:
|
|
|
|
*
|
|
|
|
* In the following paragraph, "GPL" means the GNU General Public
|
|
|
|
* License, version 3 or any later version, and "Non-GPL Code" means
|
|
|
|
* code that is governed neither by the GPL nor a license
|
|
|
|
* compatible with the GPL.
|
|
|
|
*
|
|
|
|
* You may link the code of this Program with Non-GPL Code and convey
|
|
|
|
* linked combinations including the two, provided that such Non-GPL
|
|
|
|
* Code only links to the code of this Program through those well
|
|
|
|
* defined interfaces identified in the file named EXCEPTION found in
|
|
|
|
* the source code files (the "Approved Interfaces"). The files of
|
|
|
|
* Non-GPL Code may instantiate templates or use macros or inline
|
|
|
|
* functions from the Approved Interfaces without causing the resulting
|
|
|
|
* work to be covered by the GPL. Only the copyright holders of this
|
|
|
|
* Program may make changes or additions to the list of Approved
|
|
|
|
* Interfaces.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Sumit Bose <sbose@redhat.com>
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Red Hat, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
* END COPYRIGHT BLOCK **/
|
|
|
|
|
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE 1 /* for asprintf() */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "ipa_extdom.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
|
|
|
|
2011-11-30 06:29:10 -06:00
|
|
|
int parse_request_data(struct berval *req_val, struct extdom_req **_req)
|
|
|
|
{
|
|
|
|
BerElement *ber = NULL;
|
|
|
|
ber_tag_t tag;
|
|
|
|
ber_int_t input_type;
|
|
|
|
ber_int_t request_type;
|
|
|
|
ber_int_t id;
|
|
|
|
struct extdom_req *req;
|
|
|
|
|
|
|
|
/* We expect the following request:
|
|
|
|
* ExtdomRequestValue ::= SEQUENCE {
|
|
|
|
* inputType ENUMERATED {
|
|
|
|
* sid (1),
|
|
|
|
* name (2),
|
|
|
|
* posix uid (3),
|
|
|
|
* posix gid (3)
|
|
|
|
* },
|
|
|
|
* requestType ENUMERATED {
|
|
|
|
* simple (1),
|
|
|
|
* full (2)
|
|
|
|
* },
|
|
|
|
* data InputData
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* InputData ::= CHOICE {
|
|
|
|
* sid OCTET STRING,
|
|
|
|
* name NameDomainData
|
|
|
|
* uid PosixUid,
|
|
|
|
* gid PosixGid
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* NameDomainData ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* object_name OCTET STRING
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* PosixUid ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* uid INTEGER
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* PosixGid ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* gid INTEGER
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (req_val == NULL || req_val->bv_val == NULL || req_val->bv_len == 0) {
|
|
|
|
return LDAP_PROTOCOL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ber = ber_init(req_val);
|
|
|
|
if (ber == NULL) {
|
|
|
|
return LDAP_PROTOCOL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
tag = ber_scanf(ber, "{ee", &input_type, &request_type);
|
|
|
|
if (tag == LBER_ERROR) {
|
|
|
|
ber_free(ber, 1);
|
|
|
|
return LDAP_PROTOCOL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
req = calloc(sizeof(struct extdom_req), 1);
|
|
|
|
if (req == NULL) {
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
req->input_type = input_type;
|
|
|
|
req->request_type = request_type;
|
|
|
|
|
|
|
|
switch (req->input_type) {
|
|
|
|
case INP_NAME:
|
|
|
|
tag = ber_scanf(ber, "{aa}}", &req->data.name.domain_name,
|
|
|
|
&req->data.name.object_name);
|
|
|
|
break;
|
|
|
|
case INP_SID:
|
|
|
|
tag = ber_scanf(ber, "a}", &req->data.sid);
|
|
|
|
break;
|
|
|
|
case INP_POSIX_UID:
|
|
|
|
tag = ber_scanf(ber, "{ai}}", &req->data.posix_uid.domain_name,
|
|
|
|
&id);
|
|
|
|
req->data.posix_uid.uid = (uid_t) id;
|
|
|
|
break;
|
|
|
|
case INP_POSIX_GID:
|
|
|
|
tag = ber_scanf(ber, "{ai}}", &req->data.posix_gid.domain_name,
|
|
|
|
&id);
|
|
|
|
req->data.posix_gid.gid = (gid_t) id;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ber_free(ber, 1);
|
2012-10-02 04:25:04 -05:00
|
|
|
free(req);
|
2011-11-30 06:29:10 -06:00
|
|
|
return LDAP_PROTOCOL_ERROR;
|
|
|
|
}
|
|
|
|
ber_free(ber, 1);
|
|
|
|
if (tag == LBER_ERROR) {
|
2012-10-02 04:25:04 -05:00
|
|
|
free(req);
|
2011-11-30 06:29:10 -06:00
|
|
|
return LDAP_PROTOCOL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
*_req = req;
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
void free_req_data(struct extdom_req *req)
|
2011-11-30 06:29:10 -06:00
|
|
|
{
|
2013-07-03 07:27:14 -05:00
|
|
|
if (req == NULL) {
|
2011-11-30 06:29:10 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
switch (req->input_type) {
|
|
|
|
case INP_NAME:
|
|
|
|
ber_memfree(req->data.name.domain_name);
|
|
|
|
ber_memfree(req->data.name.object_name);
|
|
|
|
break;
|
|
|
|
case INP_SID:
|
|
|
|
ber_memfree(req->data.sid);
|
|
|
|
break;
|
|
|
|
case INP_POSIX_UID:
|
|
|
|
ber_memfree(req->data.posix_uid.domain_name);
|
|
|
|
break;
|
|
|
|
case INP_POSIX_GID:
|
|
|
|
ber_memfree(req->data.posix_gid.domain_name);
|
|
|
|
break;
|
2012-08-06 07:30:38 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
free(req);
|
2012-08-06 07:30:38 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
int handle_request(struct ipa_extdom_ctx *ctx, struct extdom_req *req,
|
|
|
|
struct extdom_res **res)
|
2011-11-30 06:29:10 -06:00
|
|
|
{
|
|
|
|
int ret;
|
2013-07-03 07:27:14 -05:00
|
|
|
char *domain_name = NULL;
|
|
|
|
char *sid_str = NULL;
|
|
|
|
size_t buf_len;
|
|
|
|
char *buf = NULL;
|
|
|
|
long pw_max;
|
|
|
|
long gr_max;
|
|
|
|
struct pwd_grp pg_data;
|
|
|
|
struct passwd *pwd_result = NULL;
|
|
|
|
struct group *grp_result = NULL;
|
|
|
|
enum sss_id_type id_type;
|
|
|
|
char *fq_name = NULL;
|
|
|
|
char *sep;
|
|
|
|
|
|
|
|
|
|
|
|
pw_max = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
|
|
gr_max = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
|
|
|
|
|
|
if (pw_max == -1 && gr_max == -1) {
|
|
|
|
buf_len = 16384;
|
|
|
|
} else {
|
|
|
|
buf_len = MAX(pw_max, gr_max);
|
2011-11-30 06:29:10 -06:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
buf = malloc(sizeof(char) * buf_len);
|
|
|
|
if (buf == NULL) {
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
2012-10-02 04:25:04 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
switch (req->input_type) {
|
|
|
|
case INP_POSIX_UID:
|
|
|
|
if (req->request_type == REQ_SIMPLE) {
|
|
|
|
ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str,
|
|
|
|
&id_type);
|
|
|
|
} else {
|
|
|
|
id_type = SSS_ID_TYPE_UID;
|
|
|
|
ret = getpwuid_r(req->data.posix_uid.uid, &pg_data.data.pwd, buf,
|
|
|
|
buf_len, &pwd_result);
|
2013-04-24 07:44:54 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
domain_name = strdup(req->data.posix_uid.domain_name);
|
|
|
|
break;
|
|
|
|
case INP_POSIX_GID:
|
|
|
|
if (req->request_type == REQ_SIMPLE) {
|
|
|
|
ret = sss_nss_getsidbyid(req->data.posix_uid.uid, &sid_str,
|
|
|
|
&id_type);
|
2012-10-11 05:13:53 -05:00
|
|
|
} else {
|
2013-07-03 07:27:14 -05:00
|
|
|
id_type = SSS_ID_TYPE_GID;
|
|
|
|
ret = getgrgid_r(req->data.posix_gid.gid, &pg_data.data.grp, buf,
|
|
|
|
buf_len, &grp_result);
|
2012-10-11 05:13:53 -05:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
domain_name = strdup(req->data.posix_gid.domain_name);
|
|
|
|
break;
|
|
|
|
case INP_SID:
|
|
|
|
ret = sss_nss_getnamebysid(req->data.sid, &fq_name, &id_type);
|
|
|
|
if (ret != 0) {
|
2012-10-11 05:13:53 -05:00
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
sep = strrchr(fq_name, '@');
|
|
|
|
if (sep == NULL) {
|
2012-10-11 05:13:53 -05:00
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
ret = asprintf(&domain_name, "%s", sep+1);
|
|
|
|
if (ret == -1) {
|
2012-10-11 05:13:53 -05:00
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
2013-07-03 07:27:14 -05:00
|
|
|
domain_name = NULL; /* content is undefined according to
|
|
|
|
asprintf(3) */
|
2012-10-11 05:13:53 -05:00
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
switch(id_type) {
|
|
|
|
case SSS_ID_TYPE_UID:
|
|
|
|
case SSS_ID_TYPE_BOTH:
|
|
|
|
ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len,
|
|
|
|
&pwd_result);
|
|
|
|
break;
|
|
|
|
case SSS_ID_TYPE_GID:
|
|
|
|
ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len,
|
|
|
|
&grp_result);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
domain_name = strdup(req->data.name.domain_name);
|
|
|
|
break;
|
|
|
|
case INP_NAME:
|
|
|
|
ret = asprintf(&fq_name, "%s@%s", req->data.name.object_name,
|
|
|
|
req->data.name.domain_name);
|
|
|
|
if (ret == -1) {
|
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
fq_name = NULL; /* content is undefined according to
|
|
|
|
asprintf(3) */
|
|
|
|
goto done;
|
|
|
|
}
|
2013-04-24 07:44:54 -05:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
if (req->request_type == REQ_SIMPLE) {
|
|
|
|
ret = sss_nss_getsidbyname(fq_name, &sid_str, &id_type);
|
|
|
|
} else {
|
|
|
|
id_type = SSS_ID_TYPE_UID;
|
|
|
|
ret = getpwnam_r(fq_name, &pg_data.data.pwd, buf, buf_len,
|
|
|
|
&pwd_result);
|
|
|
|
if (ret == 0 && pwd_result == NULL) { /* no user entry found */
|
|
|
|
id_type = SSS_ID_TYPE_GID;
|
|
|
|
ret = getgrnam_r(fq_name, &pg_data.data.grp, buf, buf_len,
|
|
|
|
&grp_result);
|
2011-11-30 06:29:10 -06:00
|
|
|
}
|
2013-07-03 07:27:14 -05:00
|
|
|
}
|
2013-07-09 02:25:51 -05:00
|
|
|
domain_name = strdup(req->data.name.domain_name);
|
2013-07-03 07:27:14 -05:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = LDAP_PROTOCOL_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
if (ret != 0) {
|
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
|
|
|
} else if (ret == 0 && pwd_result == NULL && grp_result == NULL &&
|
|
|
|
sid_str == NULL) {
|
|
|
|
ret = LDAP_NO_SUCH_OBJECT;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
if (domain_name == NULL) {
|
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
ret = create_response(req, &pg_data, sid_str, id_type, domain_name, res);
|
|
|
|
if (ret != 0) {
|
|
|
|
ret = LDAP_OPERATIONS_ERROR;
|
|
|
|
goto done;
|
2011-11-30 06:29:10 -06:00
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
|
2011-11-30 06:29:10 -06:00
|
|
|
ret = LDAP_SUCCESS;
|
|
|
|
|
|
|
|
done:
|
2013-07-03 07:27:14 -05:00
|
|
|
free(buf);
|
|
|
|
free(fq_name);
|
|
|
|
free(domain_name);
|
|
|
|
free(sid_str);
|
2011-11-30 06:29:10 -06:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
int create_response(struct extdom_req *req, struct pwd_grp *pg_data,
|
|
|
|
const char *sid_str, enum sss_id_type id_type,
|
|
|
|
const char *domain_name, struct extdom_res **_res)
|
2011-11-30 06:29:10 -06:00
|
|
|
{
|
|
|
|
int ret = EFAULT;
|
|
|
|
struct extdom_res *res;
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
res = calloc(1, sizeof(struct extdom_res));
|
2011-11-30 06:29:10 -06:00
|
|
|
if (res == NULL) {
|
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (req->request_type) {
|
|
|
|
case REQ_SIMPLE:
|
|
|
|
switch (req->input_type) {
|
|
|
|
case INP_SID:
|
|
|
|
res->response_type = RESP_NAME;
|
2013-07-03 07:27:14 -05:00
|
|
|
res->data.name.domain_name = strdup(domain_name);
|
|
|
|
switch(id_type) {
|
|
|
|
case SSS_ID_TYPE_UID:
|
|
|
|
case SSS_ID_TYPE_BOTH:
|
|
|
|
res->data.name.object_name =
|
|
|
|
strdup(pg_data->data.pwd.pw_name);
|
|
|
|
break;
|
|
|
|
case SSS_ID_TYPE_GID:
|
|
|
|
res->data.name.object_name =
|
|
|
|
strdup(pg_data->data.grp.gr_name);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->data.name.domain_name == NULL
|
|
|
|
|| res->data.name.object_name == NULL) {
|
|
|
|
ret = ENOMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
break;
|
|
|
|
case INP_NAME:
|
2013-04-26 10:20:49 -05:00
|
|
|
case INP_POSIX_UID:
|
|
|
|
case INP_POSIX_GID:
|
2011-11-30 06:29:10 -06:00
|
|
|
res->response_type = RESP_SID;
|
2013-07-03 07:27:14 -05:00
|
|
|
res->data.sid = strdup(sid_str);
|
|
|
|
if (res->data.sid == NULL) {
|
|
|
|
ret = ENOMEM;
|
2011-11-30 06:29:10 -06:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case REQ_FULL:
|
2013-07-03 07:27:14 -05:00
|
|
|
switch (id_type) {
|
|
|
|
case SSS_ID_TYPE_UID:
|
|
|
|
case SSS_ID_TYPE_BOTH:
|
2011-11-30 06:29:10 -06:00
|
|
|
res->response_type = RESP_USER;
|
2013-07-03 07:27:14 -05:00
|
|
|
res->data.user.domain_name = strdup(domain_name);
|
|
|
|
res->data.user.user_name =
|
|
|
|
strdup(pg_data->data.pwd.pw_name);
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
if (res->data.user.domain_name == NULL
|
|
|
|
|| res->data.user.user_name == NULL) {
|
|
|
|
ret = ENOMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
res->data.user.uid = pg_data->data.pwd.pw_uid;
|
|
|
|
res->data.user.gid = pg_data->data.pwd.pw_gid;
|
2011-11-30 06:29:10 -06:00
|
|
|
break;
|
2013-07-03 07:27:14 -05:00
|
|
|
case SSS_ID_TYPE_GID:
|
2011-11-30 06:29:10 -06:00
|
|
|
res->response_type = RESP_GROUP;
|
2013-07-03 07:27:14 -05:00
|
|
|
res->data.group.domain_name = strdup(domain_name);
|
|
|
|
res->data.group.group_name =
|
|
|
|
strdup(pg_data->data.grp.gr_name);
|
2011-11-30 06:29:10 -06:00
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
if (res->data.group.domain_name == NULL
|
|
|
|
|| res->data.group.group_name == NULL) {
|
|
|
|
ret = ENOMEM;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
res->data.group.gid = pg_data->data.grp.gr_gid;
|
2011-11-30 06:29:10 -06:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ret = EINVAL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (ret == 0) {
|
|
|
|
*_res = res;
|
|
|
|
} else {
|
2013-07-03 07:27:14 -05:00
|
|
|
free_resp_data(res);
|
2011-11-30 06:29:10 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-07-03 07:27:14 -05:00
|
|
|
void free_resp_data(struct extdom_res *res)
|
|
|
|
{
|
|
|
|
if (res == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (res->response_type) {
|
|
|
|
case RESP_SID:
|
|
|
|
free(res->data.sid);
|
|
|
|
break;
|
|
|
|
case RESP_NAME:
|
|
|
|
free(res->data.name.domain_name);
|
|
|
|
free(res->data.name.object_name);
|
|
|
|
break;
|
|
|
|
case RESP_USER:
|
|
|
|
free(res->data.user.domain_name);
|
|
|
|
free(res->data.user.user_name);
|
|
|
|
break;
|
|
|
|
case RESP_GROUP:
|
|
|
|
free(res->data.group.domain_name);
|
|
|
|
free(res->data.group.group_name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-30 06:29:10 -06:00
|
|
|
int pack_response(struct extdom_res *res, struct berval **ret_val)
|
|
|
|
{
|
|
|
|
BerElement *ber = NULL;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* We send to follwing response:
|
|
|
|
* ExtdomResponseValue ::= SEQUENCE {
|
|
|
|
* responseType ENUMERATED {
|
|
|
|
* sid (1),
|
|
|
|
* name (2),
|
|
|
|
* posix_user (3),
|
|
|
|
* posix_group (4)
|
|
|
|
* },
|
|
|
|
* data OutputData
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* OutputData ::= CHOICE {
|
|
|
|
* sid OCTET STRING,
|
|
|
|
* name NameDomainData,
|
|
|
|
* user PosixUser,
|
|
|
|
* group PosixGroup
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* NameDomainData ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* object_name OCTET STRING
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* PosixUser ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* user_name OCTET STRING,
|
|
|
|
* uid INTEGER
|
|
|
|
* gid INTEGER
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* PosixGroup ::= SEQUENCE {
|
|
|
|
* domain_name OCTET STRING,
|
|
|
|
* group_name OCTET STRING,
|
|
|
|
* gid INTEGER
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
|
|
|
|
ber = ber_alloc_t( LBER_USE_DER );
|
|
|
|
if (ber == NULL) {
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (res->response_type) {
|
|
|
|
case RESP_SID:
|
|
|
|
ret = ber_printf(ber,"{es}", res->response_type, res->data.sid);
|
|
|
|
break;
|
|
|
|
case RESP_NAME:
|
|
|
|
ret = ber_printf(ber,"{e{ss}}", res->response_type,
|
|
|
|
res->data.name.domain_name,
|
|
|
|
res->data.name.object_name);
|
|
|
|
break;
|
|
|
|
case RESP_USER:
|
|
|
|
ret = ber_printf(ber,"{e{ssii}}", res->response_type,
|
|
|
|
res->data.user.domain_name,
|
|
|
|
res->data.user.user_name,
|
|
|
|
res->data.user.uid,
|
|
|
|
res->data.user.gid);
|
|
|
|
break;
|
|
|
|
case RESP_GROUP:
|
|
|
|
ret = ber_printf(ber,"{e{ssi}}", res->response_type,
|
|
|
|
res->data.group.domain_name,
|
|
|
|
res->data.group.group_name,
|
|
|
|
res->data.group.gid);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ber_free(ber, 1);
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == -1) {
|
|
|
|
ber_free(ber, 1);
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = ber_flatten(ber, ret_val);
|
|
|
|
if (ret == -1) {
|
|
|
|
ber_free(ber, 1);
|
|
|
|
return LDAP_OPERATIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ber_free(ber, 1);
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
}
|