#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <libintl.h>
#include <ctype.h>
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <priv.h>
#include "ns_sldap.h"
#include "ns_internal.h"
#include "ns_cache_door.h"
#include "ns_connmgmt.h"
#define _NIS_FILTER "nisdomain=*"
#define _NIS_DOMAIN "nisdomain"
static const char *nis_domain_attrs[] = {
_NIS_DOMAIN,
(char *)NULL
};
static int validate_filter(ns_ldap_cookie_t *cookie);
void
__ns_ldap_freeEntry(ns_ldap_entry_t *ep)
{
int j, k = 0;
if (ep == NULL)
return;
if (ep->attr_pair == NULL) {
free(ep);
return;
}
for (j = 0; j < ep->attr_count; j++) {
if (ep->attr_pair[j] == NULL)
continue;
if (ep->attr_pair[j]->attrname)
free(ep->attr_pair[j]->attrname);
if (ep->attr_pair[j]->attrvalue) {
for (k = 0; (k < ep->attr_pair[j]->value_count) &&
(ep->attr_pair[j]->attrvalue[k]); k++) {
free(ep->attr_pair[j]->attrvalue[k]);
}
free(ep->attr_pair[j]->attrvalue);
}
free(ep->attr_pair[j]);
}
free(ep->attr_pair);
free(ep);
}
static void
_freeControlList(LDAPControl ***ctrls)
{
LDAPControl **ctrl;
if (ctrls == NULL || *ctrls == NULL)
return;
for (ctrl = *ctrls; *ctrl != NULL; ctrl++)
ldap_control_free(*ctrl);
free(*ctrls);
*ctrls = NULL;
}
static char *
_cvtRDN(const char *service, const char *rdn)
{
char **attrs, **mapped_attrs, **mapp, *type, *value, *attr;
char *new_rdn = NULL;
int nAttr = 0, i, attr_mapped, len = 0;
if ((attrs = ldap_explode_rdn(rdn, 0)) == NULL)
return (NULL);
for (nAttr = 0; attrs[nAttr] != NULL; nAttr++)
;
if ((mapped_attrs = (char **)calloc(nAttr, sizeof (char *))) == NULL) {
ldap_value_free(attrs);
return (NULL);
}
attr_mapped = 0;
for (i = 0; i < nAttr; i++) {
if ((type = strtok_r(attrs[i], "=", &value)) == NULL ||
value == NULL)
goto cleanup;
mapp = __ns_ldap_getOrigAttribute(service, type);
if (mapp != NULL && mapp[0] != NULL) {
type = mapp[0];
attr_mapped = 1;
len = strlen(type) + strlen(value) + 2;
if ((attr = (char *)calloc(1, len)) == NULL) {
__s_api_free2dArray(mapp);
goto cleanup;
}
(void) snprintf(attr, len, "%s=%s", type, value);
mapped_attrs[i] = attr;
} else {
type[strlen(type)] = '=';
}
__s_api_free2dArray(mapp);
}
if (attr_mapped == 0)
goto cleanup;
len = 0;
for (i = 0; i < nAttr; i++) {
if (mapped_attrs[i])
len += strlen(mapped_attrs[i]);
else
len += strlen(attrs[i]);
len++;
}
if ((new_rdn = (char *)calloc(1, ++len)) == NULL)
goto cleanup;
for (i = 0; i < nAttr; i++) {
if (i > 0)
(void) strlcat(new_rdn, "+", len);
if (mapped_attrs[i])
(void) strlcat(new_rdn, mapped_attrs[i], len);
else
(void) strlcat(new_rdn, attrs[i], len);
}
cleanup:
ldap_value_free(attrs);
if (mapped_attrs) {
if (attr_mapped) {
for (i = 0; i < nAttr; i++) {
if (mapped_attrs[i])
free(mapped_attrs[i]);
}
}
free(mapped_attrs);
}
return (new_rdn);
}
static char *
_cvtDN(const char *service, const char *dn)
{
char **mapped_rdns;
char **rdns, *new_rdn, *new_dn = NULL;
int nRdn = 0, i, len = 0, rdn_mapped;
if (service == NULL || dn == NULL)
return (NULL);
if ((rdns = ldap_explode_dn(dn, 0)) == NULL)
return (NULL);
for (nRdn = 0; rdns[nRdn] != NULL; nRdn++)
;
if ((mapped_rdns = (char **)calloc(nRdn, sizeof (char *))) == NULL) {
ldap_value_free(rdns);
return (NULL);
}
rdn_mapped = 0;
for (i = 0; i < nRdn; i++) {
if ((new_rdn = _cvtRDN(service, rdns[i])) != NULL) {
mapped_rdns[i] = new_rdn;
rdn_mapped = 1;
}
}
if (rdn_mapped == 0) {
new_dn = strdup(dn);
goto cleanup;
}
for (i = 0; i < nRdn; i++) {
if (mapped_rdns[i])
len += strlen(mapped_rdns[i]);
else
len += strlen(rdns[i]);
len ++;
}
if ((new_dn = (char *)calloc(1, ++len)) == NULL)
goto cleanup;
for (i = 0; i < nRdn; i++) {
if (i > 0)
(void) strlcat(new_dn, ",", len);
if (mapped_rdns[i])
(void) strlcat(new_dn, mapped_rdns[i], len);
else
(void) strlcat(new_dn, rdns[i], len);
}
cleanup:
ldap_value_free(rdns);
if (mapped_rdns) {
if (rdn_mapped) {
for (i = 0; i < nRdn; i++) {
if (mapped_rdns[i])
free(mapped_rdns[i]);
}
}
free(mapped_rdns);
}
return (new_dn);
}
static int
__s_api_cvtEntry(LDAP *ld, const char *service, LDAPMessage *e, int flags,
ns_ldap_entry_t **ret, ns_ldap_error_t **error)
{
ns_ldap_entry_t *ep = NULL;
ns_ldap_attr_t **ap = NULL;
BerElement *ber;
char *attr = NULL;
char **vals = NULL;
char **mapping;
char *dn;
int nAttrs = 0;
int i, j, k = 0;
char **gecos_mapping = NULL;
int gecos_val_index[3] = { -1, -1, -1};
char errstr[MAXERROR];
int schema_mapping_existed = FALSE;
int gecos_mapping_existed = FALSE;
int gecos_attr_matched;
int auto_service = FALSE;
int rc = NS_LDAP_SUCCESS;
if (e == NULL || ret == NULL || error == NULL)
return (NS_LDAP_INVALID_PARAM);
*error = NULL;
ep = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
if (ep == NULL)
return (NS_LDAP_MEMORY);
if (service != NULL &&
(strncasecmp(service, "auto_", 5) == 0 ||
strcasecmp(service, "automount") == 0))
auto_service = TRUE;
mapping = __ns_ldap_getOrigAttribute(service,
NS_HASH_SCHEMA_MAPPING_EXISTED);
if (mapping) {
schema_mapping_existed = TRUE;
__s_api_free2dArray(mapping);
mapping = NULL;
} else if (auto_service) {
mapping = __ns_ldap_getOrigAttribute("automount",
NS_HASH_SCHEMA_MAPPING_EXISTED);
if (mapping) {
schema_mapping_existed = TRUE;
__s_api_free2dArray(mapping);
mapping = NULL;
}
}
nAttrs = 1;
for (attr = ldap_first_attribute(ld, e, &ber); attr != NULL;
attr = ldap_next_attribute(ld, e, ber)) {
nAttrs++;
ldap_memfree(attr);
attr = NULL;
}
ber_free(ber, 0);
ber = NULL;
ep->attr_count = nAttrs;
ap = (ns_ldap_attr_t **)calloc(ep->attr_count + 1,
sizeof (ns_ldap_attr_t *));
if (ap == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ep->attr_pair = ap;
dn = ldap_get_dn(ld, e);
ap[0] = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
if (ap[0] == NULL) {
ldap_memfree(dn);
dn = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
if ((ap[0]->attrname = strdup("dn")) == NULL) {
ldap_memfree(dn);
dn = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_INVALID_PARAM);
}
ap[0]->value_count = 1;
if ((ap[0]->attrvalue = (char **)
calloc(2, sizeof (char *))) == NULL) {
ldap_memfree(dn);
dn = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
if (schema_mapping_existed && ((flags & NS_LDAP_NOT_CVT_DN) == 0))
ap[0]->attrvalue[0] = _cvtDN(service, dn);
else
ap[0]->attrvalue[0] = strdup(dn);
if (ap[0]->attrvalue[0] == NULL) {
ldap_memfree(dn);
dn = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ldap_memfree(dn);
dn = NULL;
if ((flags & NS_LDAP_NOMAP) == 0 && auto_service &&
schema_mapping_existed) {
rc = __s_api_convert_automountmapname(service,
&ap[0]->attrvalue[0],
error);
if (rc != NS_LDAP_SUCCESS) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (rc);
}
}
for (attr = ldap_first_attribute(ld, e, &ber), j = 1;
attr != NULL && j != nAttrs;
attr = ldap_next_attribute(ld, e, ber), j++) {
if ((ap[j] = (ns_ldap_attr_t *)
calloc(1, sizeof (ns_ldap_attr_t))) == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
if ((flags & NS_LDAP_NOMAP) || schema_mapping_existed == FALSE)
mapping = NULL;
else
mapping = __ns_ldap_getOrigAttribute(service, attr);
if (mapping == NULL && auto_service &&
schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0)
mapping = __ns_ldap_getOrigAttribute("automount",
attr);
if (mapping == NULL) {
if ((ap[j]->attrname = strdup(attr)) == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
} else {
if (strcasecmp(mapping[0], "gecos") == 0) {
ap[j]->attrname = strdup(attr);
gecos_mapping_existed = TRUE;
} else {
ap[j]->attrname = strdup(mapping[0]);
}
if (ap[j]->attrname == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
if (strcasecmp(mapping[0], "gecos") == 0) {
if (gecos_mapping == NULL) {
gecos_mapping =
__ns_ldap_getMappedAttributes(
service, mapping[0]);
if (gecos_mapping == NULL ||
gecos_mapping[0] == NULL) {
(void) sprintf(errstr,
gettext(
"Attribute mapping "
"inconsistency "
"found for attributes "
"'%s' and '%s'."),
mapping[0], attr);
syslog(LOG_ERR, "libsldap: %s",
errstr);
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
__s_api_free2dArray(mapping);
mapping = NULL;
if (gecos_mapping)
__s_api_free2dArray(
gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_INTERNAL);
}
}
gecos_attr_matched = FALSE;
for (i = 0; i < 3 && gecos_mapping[i]; i++) {
if (gecos_mapping[i] &&
strcasecmp(gecos_mapping[i],
attr) == 0) {
gecos_val_index[i] = j;
gecos_attr_matched = TRUE;
break;
}
}
if (gecos_attr_matched == FALSE) {
(void) sprintf(errstr,
gettext(
"Attribute mapping "
"inconsistency "
"found for attributes "
"'%s' and '%s'."),
mapping[0], attr);
syslog(LOG_ERR, "libsldap: %s", errstr);
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
__s_api_free2dArray(mapping);
mapping = NULL;
__s_api_free2dArray(gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_INTERNAL);
}
}
__s_api_free2dArray(mapping);
mapping = NULL;
}
if ((vals = ldap_get_values(ld, e, attr)) != NULL) {
if ((ap[j]->value_count =
ldap_count_values(vals)) == 0) {
ldap_value_free(vals);
vals = NULL;
continue;
} else {
ap[j]->attrvalue = (char **)
calloc(ap[j]->value_count+1,
sizeof (char *));
if (ap[j]->attrvalue == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(
gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
}
if ((flags & NS_LDAP_NOMAP) == 0 &&
schema_mapping_existed && ap[j]->attrname &&
strcasecmp(ap[j]->attrname, "objectclass") == 0) {
for (k = 0; k < ap[j]->value_count; k++) {
mapping =
__ns_ldap_getOrigObjectClass(
service, vals[k]);
if (mapping == NULL && auto_service)
mapping =
__ns_ldap_getOrigObjectClass(
"automount", vals[k]);
if (mapping == NULL) {
ap[j]->attrvalue[k] =
strdup(vals[k]);
} else {
ap[j]->attrvalue[k] =
strdup(mapping[0]);
__s_api_free2dArray(mapping);
mapping = NULL;
}
if (ap[j]->attrvalue[k] == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(
gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
}
} else {
for (k = 0; k < ap[j]->value_count; k++) {
if ((ap[j]->attrvalue[k] =
strdup(vals[k])) == NULL) {
ber_free(ber, 0);
ber = NULL;
__ns_ldap_freeEntry(ep);
ep = NULL;
if (gecos_mapping)
__s_api_free2dArray(
gecos_mapping);
gecos_mapping = NULL;
return (NS_LDAP_MEMORY);
}
}
}
ap[j]->attrvalue[k] = NULL;
ldap_value_free(vals);
vals = NULL;
}
ldap_memfree(attr);
attr = NULL;
}
ber_free(ber, 0);
ber = NULL;
if (gecos_mapping) {
__s_api_free2dArray(gecos_mapping);
gecos_mapping = NULL;
}
if (schema_mapping_existed && gecos_mapping_existed) {
int f = -1;
for (i = 0; i < 3; i++) {
k = gecos_val_index[i];
if (k != -1 && f == -1)
f = k;
if (k != -1 && ap[k]->value_count > 0 &&
ap[k]->attrvalue[0] &&
strlen(ap[k]->attrvalue[0]) > 0) {
if (k == f) {
ap[nAttrs] = (ns_ldap_attr_t *)
calloc(1,
sizeof (ns_ldap_attr_t));
if (ap[nAttrs] == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ap[nAttrs]->attrvalue = (char **)calloc(
2, sizeof (char *));
if (ap[nAttrs]->attrvalue == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ap[nAttrs]->attrvalue[0] =
(char *)calloc(
strlen(ap[f]->attrvalue[0]) +
2, 1);
if (ap[nAttrs]->attrvalue[0] == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
(void) strcpy(ap[nAttrs]->attrvalue[0],
ap[f]->attrvalue[0]);
ap[nAttrs]->attrname = strdup("gecos");
if (ap[nAttrs]->attrname == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ap[nAttrs]->value_count = 1;
ep->attr_count = nAttrs + 1;
} else {
char *tmp = NULL;
tmp = (char *)realloc(
ap[nAttrs]->attrvalue[0],
strlen(ap[nAttrs]->
attrvalue[0]) +
strlen(ap[k]->
attrvalue[0]) + 2);
if (tmp == NULL) {
__ns_ldap_freeEntry(ep);
ep = NULL;
return (NS_LDAP_MEMORY);
}
ap[nAttrs]->attrvalue[0] = tmp;
(void) strcat(ap[nAttrs]->attrvalue[0],
",");
(void) strcat(ap[nAttrs]->attrvalue[0],
ap[k]->attrvalue[0]);
}
}
}
}
*ret = ep;
return (NS_LDAP_SUCCESS);
}
static int
__s_api_getEntry(ns_ldap_cookie_t *cookie)
{
ns_ldap_entry_t *curEntry = NULL;
int ret;
#ifdef DEBUG
(void) fprintf(stderr, "__s_api_getEntry START\n");
#endif
if (cookie->resultMsg == NULL) {
return (NS_LDAP_INVALID_PARAM);
}
ret = __s_api_cvtEntry(cookie->conn->ld, cookie->service,
cookie->resultMsg, cookie->i_flags,
&curEntry, &cookie->errorp);
if (ret != NS_LDAP_SUCCESS) {
return (ret);
}
if (cookie->result == NULL) {
cookie->result = (ns_ldap_result_t *)
calloc(1, sizeof (ns_ldap_result_t));
if (cookie->result == NULL) {
__ns_ldap_freeEntry(curEntry);
curEntry = NULL;
return (NS_LDAP_MEMORY);
}
cookie->result->entry = curEntry;
cookie->nextEntry = curEntry;
} else {
cookie->nextEntry->next = curEntry;
cookie->nextEntry = curEntry;
}
cookie->result->entries_count++;
return (NS_LDAP_SUCCESS);
}
static int
__s_api_get_cachemgr_data(const char *type, const char *from, char **to)
{
union {
ldap_data_t s_d;
char s_b[DOORBUFFERSIZE];
} space;
ldap_data_t *sptr;
int ndata;
int adata;
int rc;
#ifdef DEBUG
(void) fprintf(stderr, "__s_api_get_cachemgr_data START\n");
#endif
if (__s_api_isStandalone()) {
return (-1);
}
if (from == NULL || from[0] == '\0' || to == NULL)
return (-1);
*to = NULL;
(void) memset(space.s_b, 0, DOORBUFFERSIZE);
space.s_d.ldap_call.ldap_callnumber = GETCACHE;
(void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
"%s%s%s",
type,
DOORLINESEP,
from);
ndata = sizeof (space);
adata = sizeof (ldap_call_t) +
strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
sptr = &space.s_d;
rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
if (rc != NS_CACHE_SUCCESS)
return (-1);
else
*to = strdup(sptr->ldap_ret.ldap_u.buff);
return (NS_LDAP_SUCCESS);
}
static int
__s_api_set_cachemgr_data(const char *type, const char *from, const char *to)
{
union {
ldap_data_t s_d;
char s_b[DOORBUFFERSIZE];
} space;
ldap_data_t *sptr;
int ndata;
int adata;
int rc;
#ifdef DEBUG
(void) fprintf(stderr, "__s_api_set_cachemgr_data START\n");
#endif
if (__s_api_isStandalone()) {
return (-1);
}
if ((from == NULL) || (from[0] == '\0') ||
(to == NULL) || (to[0] == '\0'))
return (-1);
(void) memset(space.s_b, 0, DOORBUFFERSIZE);
space.s_d.ldap_call.ldap_callnumber = SETCACHE;
(void) snprintf(space.s_d.ldap_call.ldap_u.domainname,
DOORBUFFERSIZE - sizeof (space.s_d.ldap_call.ldap_callnumber),
"%s%s%s%s%s",
type,
DOORLINESEP,
from,
DOORLINESEP,
to);
ndata = sizeof (space);
adata = sizeof (ldap_call_t) +
strlen(space.s_d.ldap_call.ldap_u.domainname) + 1;
sptr = &space.s_d;
rc = __ns_ldap_trydoorcall(&sptr, &ndata, &adata);
if (rc != NS_CACHE_SUCCESS)
return (-1);
return (NS_LDAP_SUCCESS);
}
static char *
__s_api_remove_rdn_space(char *rdn)
{
char *tf, *tl, *vf, *vl, *eqsign;
if (strchr(rdn, SPACETOK) == NULL)
return (rdn);
eqsign = strchr(rdn, '=');
if (eqsign == NULL)
return (rdn);
tf = rdn;
tl = eqsign - 1;
vf = eqsign + 1;
vl = rdn + strlen(rdn) - 1;
*eqsign = '\0';
while (tf < tl && *tf == SPACETOK)
tf++;
while (tf < tl && *tl == SPACETOK)
tl--;
*(++tl) = '=';
while (vf < vl && *vf == SPACETOK)
vf++;
while (vf < vl && *vl == SPACETOK)
*vl-- = '\0';
if (vf != tl + 1)
(void) strcpy(tl + 1, vf);
return (tf);
}
static
ns_ldap_cookie_t *
init_search_state_machine()
{
ns_ldap_cookie_t *cookie;
ns_config_t *cfg;
cookie = (ns_ldap_cookie_t *)calloc(1, sizeof (ns_ldap_cookie_t));
if (cookie == NULL)
return (NULL);
cookie->state = INIT;
cfg = __s_api_loadrefresh_config();
cookie->connectionId = -1;
if (cfg == NULL ||
cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_ptype == NS_UNKNOWN) {
cookie->search_timeout.tv_sec = NS_DEFAULT_SEARCH_TIMEOUT;
} else {
cookie->search_timeout.tv_sec =
cfg->paramList[NS_LDAP_SEARCH_TIME_P].ns_i;
}
if (cfg != NULL)
__s_api_release_config(cfg);
cookie->search_timeout.tv_usec = 0;
return (cookie);
}
static void
delete_search_cookie(ns_ldap_cookie_t *cookie)
{
if (cookie == NULL)
return;
if (cookie->connectionId > -1)
DropConnection(cookie->connectionId, cookie->i_flags);
if (cookie->filter)
free(cookie->filter);
if (cookie->i_filter)
free(cookie->i_filter);
if (cookie->service)
free(cookie->service);
if (cookie->sdlist)
(void) __ns_ldap_freeSearchDescriptors(&(cookie->sdlist));
if (cookie->result)
(void) __ns_ldap_freeResult(&cookie->result);
if (cookie->attribute)
__s_api_free2dArray(cookie->attribute);
if (cookie->errorp)
(void) __ns_ldap_freeError(&cookie->errorp);
if (cookie->reflist)
__s_api_deleteRefInfo(cookie->reflist);
if (cookie->basedn)
free(cookie->basedn);
if (cookie->ctrlCookie)
ber_bvfree(cookie->ctrlCookie);
_freeControlList(&cookie->p_serverctrls);
if (cookie->resultctrl)
ldap_controls_free(cookie->resultctrl);
free(cookie);
}
static int
get_mapped_filter(ns_ldap_cookie_t *cookie, char **new_filter)
{
typedef struct filter_mapping_info {
char oc_or_attr;
char *name_start;
char *name_end;
char *veq_pos;
char *from_name;
char *to_name;
char **mapping;
} filter_mapping_info_t;
char *c, *last_copied;
char *filter_c, *filter_c_next;
char *key, *tail, *head;
char errstr[MAXERROR];
int num_eq = 0, num_veq = 0;
boolean_t in_quote = B_FALSE;
boolean_t is_value = B_FALSE;
int i, j, oc_len, len;
boolean_t at_least_one = B_FALSE;
filter_mapping_info_t **info, *info1;
char **mapping;
char *service, *filter, *err;
boolean_t auto_service = B_FALSE;
if (cookie == NULL || new_filter == NULL)
return (NS_LDAP_INVALID_PARAM);
*new_filter = NULL;
service = cookie->service;
filter = cookie->filter;
for (c = filter; *c; c++) {
if (*c == TOKENSEPARATOR)
num_eq++;
}
if (service != NULL && strncasecmp(service, "auto_", 5) == 0)
auto_service = TRUE;
mapping = __ns_ldap_getOrigAttribute(service,
NS_HASH_SCHEMA_MAPPING_EXISTED);
if (mapping == NULL && auto_service)
mapping = __ns_ldap_getOrigAttribute(
"automount", NS_HASH_SCHEMA_MAPPING_EXISTED);
if (mapping)
__s_api_free2dArray(mapping);
else
return (NS_LDAP_SUCCESS);
if (num_eq == 0)
return (NS_LDAP_SUCCESS);
filter_c = strdup(filter);
if (filter_c == NULL)
return (NS_LDAP_MEMORY);
filter_c_next = filter_c;
info = (filter_mapping_info_t **)calloc(num_eq + 1,
sizeof (filter_mapping_info_t *));
if (info == NULL) {
free(filter_c);
return (NS_LDAP_MEMORY);
}
for (c = filter_c; *c; c++) {
switch (*c) {
case TOKENSEPARATOR:
if (!in_quote && !is_value) {
info1 = (filter_mapping_info_t *)calloc(1,
sizeof (filter_mapping_info_t));
if (info1 == NULL) {
free(filter_c);
for (i = 0; i < num_veq; i++)
free(info[i]);
free(info);
return (NS_LDAP_MEMORY);
}
info[num_veq] = info1;
info[num_veq++]->veq_pos = c;
is_value = B_TRUE;
}
break;
case CPARATOK:
if (!in_quote)
is_value = B_FALSE;
break;
case QUOTETOK:
in_quote = (in_quote == B_FALSE);
break;
case '\\':
if (!in_quote)
if (*(++c) == '\0')
c--;
break;
}
}
oc_len = strlen("objectclass");
for (i = 0; i < num_veq; i++) {
for (tail = info[i]->veq_pos; (tail > filter_c_next) &&
(*(tail - 1) == SPACETOK); tail--)
;
*tail = '\0';
info[i]->name_end = tail - filter_c - 1 + filter;
key = filter_c_next;
for (c = tail; filter_c_next <= c; c--) {
if (*c == OPARATOK ||
*c == SPACETOK) {
key = c + 1;
break;
}
}
info[i]->name_start = key - filter_c + filter;
if ((key + oc_len) <= tail) {
if (strncasecmp(key, "objectclass",
oc_len) == 0) {
head = info[i]->veq_pos;
for (head = info[i]->veq_pos + 1;
*head && *head == SPACETOK; head++)
;
if (!(*head))
continue;
info[i]->name_start = head - filter_c +
filter;
for (c = head; ; c++) {
if (*c == CPARATOK ||
*c == '\0' ||
*c == SPACETOK) {
*c = '\0';
info[i]->name_end =
c - filter_c - 1 +
filter;
filter_c_next = c + 1;
info[i]->oc_or_attr = 'o';
info[i]->from_name = head;
break;
}
}
}
}
if (info[i]->from_name == NULL && strlen(key) > 0) {
info[i]->oc_or_attr = 'a';
info[i]->from_name = key;
}
}
for (i = 0; i < num_veq; i++) {
if (info[i]->from_name == NULL)
continue;
if (info[i]->oc_or_attr == 'a')
info[i]->mapping =
__ns_ldap_getMappedAttributes(service,
info[i]->from_name);
else
info[i]->mapping =
__ns_ldap_getMappedObjectClass(service,
info[i]->from_name);
if (info[i]->mapping == NULL && auto_service) {
if (info[i]->oc_or_attr == 'a')
info[i]->mapping =
__ns_ldap_getMappedAttributes("automount",
info[i]->from_name);
else
info[i]->mapping =
__ns_ldap_getMappedObjectClass("automount",
info[i]->from_name);
}
if (info[i]->mapping == NULL ||
info[i]->mapping[0] == NULL) {
info[i]->to_name = NULL;
} else if (info[i]->mapping[1] == NULL) {
info[i]->to_name = info[i]->mapping[0];
at_least_one = TRUE;
} else {
__s_api_free2dArray(info[i]->mapping);
(void) sprintf(errstr,
gettext(
"Multiple attribute or objectclass "
"mapping for '%s' in filter "
"'%s' not allowed."),
info[i]->from_name, filter);
err = strdup(errstr);
if (err) {
MKERROR(LOG_WARNING, cookie->errorp,
NS_CONFIG_SYNTAX,
err, NS_LDAP_MEMORY);
}
free(filter_c);
for (j = 0; j < num_veq; j++) {
if (info[j]->mapping)
__s_api_free2dArray(
info[j]->mapping);
free(info[j]);
}
free(info);
return (NS_LDAP_CONFIG);
}
}
if (at_least_one) {
len = strlen(filter);
last_copied = filter - 1;
for (i = 0; i < num_veq; i++) {
if (info[i]->to_name)
len += strlen(info[i]->to_name);
}
*new_filter = (char *)calloc(1, len);
if (*new_filter == NULL) {
free(filter_c);
for (j = 0; j < num_veq; j++) {
if (info[j]->mapping)
__s_api_free2dArray(
info[j]->mapping);
free(info[j]);
}
free(info);
return (NS_LDAP_MEMORY);
}
for (i = 0; i < num_veq; i++) {
if (info[i]->to_name != NULL &&
info[i]->to_name != NULL) {
if ((last_copied + 1) != info[i]->name_start)
(void) strncat(*new_filter,
last_copied + 1,
info[i]->name_start -
last_copied - 1);
last_copied = info[i]->name_end;
(void) strcat(*new_filter, info[i]->to_name);
}
if (i == (num_veq -1) &&
info[i]->name_end <
(filter + strlen(filter)))
(void) strncat(*new_filter, last_copied + 1,
filter + strlen(filter) -
last_copied - 1);
}
}
free(filter_c);
for (j = 0; j < num_veq; j++) {
if (info[j]->mapping)
__s_api_free2dArray(info[j]->mapping);
free(info[j]);
}
free(info);
return (NS_LDAP_SUCCESS);
}
static int
setup_next_search(ns_ldap_cookie_t *cookie)
{
ns_ldap_search_desc_t *dptr;
int scope;
char *filter, *str;
int baselen;
int rc;
void **param;
dptr = *cookie->sdpos;
scope = cookie->i_flags & (NS_LDAP_SCOPE_BASE |
NS_LDAP_SCOPE_ONELEVEL |
NS_LDAP_SCOPE_SUBTREE);
if (scope)
cookie->scope = scope;
else
cookie->scope = dptr->scope;
switch (cookie->scope) {
case NS_LDAP_SCOPE_BASE:
cookie->scope = LDAP_SCOPE_BASE;
break;
case NS_LDAP_SCOPE_ONELEVEL:
cookie->scope = LDAP_SCOPE_ONELEVEL;
break;
case NS_LDAP_SCOPE_SUBTREE:
cookie->scope = LDAP_SCOPE_SUBTREE;
break;
}
filter = NULL;
if (cookie->use_filtercb && cookie->init_filter_cb &&
dptr->filter && strlen(dptr->filter) > 0) {
(*cookie->init_filter_cb)(dptr, &filter,
cookie->userdata);
}
if (filter == NULL) {
if (cookie->i_filter == NULL) {
cookie->err_rc = NS_LDAP_INVALID_PARAM;
return (-1);
} else {
if (cookie->filter)
free(cookie->filter);
cookie->filter = strdup(cookie->i_filter);
if (cookie->filter == NULL) {
cookie->err_rc = NS_LDAP_MEMORY;
return (-1);
}
}
} else {
if (cookie->filter)
free(cookie->filter);
cookie->filter = strdup(filter);
free(filter);
if (cookie->filter == NULL) {
cookie->err_rc = NS_LDAP_MEMORY;
return (-1);
}
}
filter = NULL;
if (cookie->service) {
rc = get_mapped_filter(cookie, &filter);
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
} else {
if (filter) {
free(cookie->filter);
cookie->filter = filter;
}
}
}
rc = validate_filter(cookie);
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
}
baselen = strlen(dptr->basedn);
if (baselen > 0 && dptr->basedn[baselen-1] == COMMATOK) {
rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
(void ***)¶m, &cookie->errorp);
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
}
str = ((char **)param)[0];
baselen += strlen(str)+1;
if (cookie->basedn)
free(cookie->basedn);
cookie->basedn = (char *)malloc(baselen);
if (cookie->basedn == NULL) {
cookie->err_rc = NS_LDAP_MEMORY;
return (-1);
}
(void) strcpy(cookie->basedn, dptr->basedn);
(void) strcat(cookie->basedn, str);
(void) __ns_ldap_freeParam(¶m);
} else {
if (cookie->basedn)
free(cookie->basedn);
cookie->basedn = strdup(dptr->basedn);
}
return (0);
}
static int
setup_referral_search(ns_ldap_cookie_t *cookie)
{
ns_referral_info_t *ref;
ref = cookie->refpos;
cookie->scope = ref->refScope;
if (cookie->filter) {
free(cookie->filter);
}
cookie->filter = strdup(ref->refFilter);
if (cookie->basedn) {
free(cookie->basedn);
}
cookie->basedn = strdup(ref->refDN);
if (cookie->filter == NULL || cookie->basedn == NULL) {
cookie->err_rc = NS_LDAP_MEMORY;
return (-1);
}
return (0);
}
static int
get_current_session(ns_ldap_cookie_t *cookie)
{
ConnectionID connectionId = -1;
Connection *conp = NULL;
int rc;
int fail_if_new_pwd_reqd = 1;
rc = __s_api_getConnection(NULL, cookie->i_flags,
cookie->i_auth, &connectionId, &conp,
&cookie->errorp, fail_if_new_pwd_reqd,
cookie->nopasswd_acct_mgmt, cookie->conn_user);
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
&cookie->errorp);
cookie->errorp = NULL;
rc = NS_LDAP_SUCCESS;
}
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
}
cookie->conn = conp;
cookie->connectionId = connectionId;
return (0);
}
static int
get_next_session(ns_ldap_cookie_t *cookie)
{
ConnectionID connectionId = -1;
Connection *conp = NULL;
int rc;
int fail_if_new_pwd_reqd = 1;
if (cookie->connectionId > -1) {
DropConnection(cookie->connectionId, cookie->i_flags);
cookie->connectionId = -1;
}
if (cookie->conn_user != NULL &&
cookie->conn_user->conn_mt != NULL)
__s_api_conn_mt_return(cookie->conn_user);
rc = __s_api_getConnection(NULL, cookie->i_flags,
cookie->i_auth, &connectionId, &conp,
&cookie->errorp, fail_if_new_pwd_reqd,
cookie->nopasswd_acct_mgmt, cookie->conn_user);
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
&cookie->errorp);
cookie->errorp = NULL;
rc = NS_LDAP_SUCCESS;
}
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
}
cookie->conn = conp;
cookie->connectionId = connectionId;
return (0);
}
static int
get_referral_session(ns_ldap_cookie_t *cookie)
{
ConnectionID connectionId = -1;
Connection *conp = NULL;
int rc;
int fail_if_new_pwd_reqd = 1;
if (cookie->connectionId > -1) {
DropConnection(cookie->connectionId, cookie->i_flags);
cookie->connectionId = -1;
}
if (cookie->conn_user != NULL) {
if (cookie->conn_user->conn_mt != NULL)
__s_api_conn_mt_return(cookie->conn_user);
cookie->conn_user->referral = B_TRUE;
}
rc = __s_api_getConnection(cookie->refpos->refHost, 0,
cookie->i_auth, &connectionId, &conp,
&cookie->errorp, fail_if_new_pwd_reqd,
cookie->nopasswd_acct_mgmt, cookie->conn_user);
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
&cookie->errorp);
cookie->errorp = NULL;
rc = NS_LDAP_SUCCESS;
}
if (rc != NS_LDAP_SUCCESS) {
cookie->err_rc = rc;
return (-1);
}
cookie->conn = conp;
cookie->connectionId = connectionId;
return (0);
}
static int
paging_supported(ns_ldap_cookie_t *cookie)
{
int rc;
cookie->listType = 0;
rc = __s_api_isCtrlSupported(cookie->conn,
LDAP_CONTROL_VLVREQUEST);
if (rc == NS_LDAP_SUCCESS) {
cookie->listType = VLVCTRLFLAG;
return (1);
}
rc = __s_api_isCtrlSupported(cookie->conn,
LDAP_CONTROL_SIMPLE_PAGE);
if (rc == NS_LDAP_SUCCESS) {
cookie->listType = SIMPLEPAGECTRLFLAG;
return (1);
}
return (0);
}
typedef struct servicesorttype {
char *service;
ns_srvsidesort_t type;
} servicesorttype_t;
static servicesorttype_t *sort_type = NULL;
static int sort_type_size = 0;
static int sort_type_hwm = 0;
static mutex_t sort_type_mutex = DEFAULTMUTEX;
static ns_srvsidesort_t
get_srvsidesort_type(char *service)
{
int i;
ns_srvsidesort_t type = SSS_UNKNOWN;
if (service == NULL)
return (type);
(void) mutex_lock(&sort_type_mutex);
if (sort_type != NULL) {
for (i = 0; i < sort_type_hwm; i++) {
if (strcmp(sort_type[i].service, service) == 0) {
type = sort_type[i].type;
break;
}
}
}
(void) mutex_unlock(&sort_type_mutex);
return (type);
}
static void
update_srvsidesort_type(char *service, ns_srvsidesort_t type)
{
int i, size;
servicesorttype_t *tmp;
if (service == NULL)
return;
(void) mutex_lock(&sort_type_mutex);
for (i = 0; i < sort_type_hwm; i++) {
if (strcmp(sort_type[i].service, service) == 0) {
sort_type[i].type = type;
(void) mutex_unlock(&sort_type_mutex);
return;
}
}
if (sort_type == NULL) {
size = 10;
tmp = malloc(size * sizeof (servicesorttype_t));
if (tmp == NULL) {
(void) mutex_unlock(&sort_type_mutex);
return;
}
sort_type = tmp;
sort_type_size = size;
} else if (sort_type_hwm >= sort_type_size) {
size = sort_type_size + 10;
tmp = realloc(sort_type, size * sizeof (servicesorttype_t));
if (tmp == NULL) {
(void) mutex_unlock(&sort_type_mutex);
return;
}
sort_type = tmp;
sort_type_size = size;
}
sort_type[sort_type_hwm].service = strdup(service);
if (sort_type[sort_type_hwm].service == NULL) {
(void) mutex_unlock(&sort_type_mutex);
return;
}
sort_type[sort_type_hwm].type = type;
sort_type_hwm++;
(void) mutex_unlock(&sort_type_mutex);
}
static int
setup_vlv_params(ns_ldap_cookie_t *cookie)
{
LDAPControl **ctrls;
LDAPsortkey **sortkeylist;
LDAPControl *sortctrl = NULL;
LDAPControl *vlvctrl = NULL;
LDAPVirtualList vlist;
char *sortattr;
int rc;
int free_sort = FALSE;
_freeControlList(&cookie->p_serverctrls);
if (cookie->sortTypeTry == SSS_UNKNOWN)
cookie->sortTypeTry = get_srvsidesort_type(cookie->service);
if (cookie->sortTypeTry == SSS_UNKNOWN)
cookie->sortTypeTry = SSS_SINGLE_ATTR;
if (cookie->sortTypeTry == SSS_SINGLE_ATTR) {
if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
cookie->i_sortattr) {
sortattr = __ns_ldap_mapAttribute(cookie->service,
cookie->i_sortattr);
free_sort = TRUE;
} else if (cookie->i_sortattr) {
sortattr = (char *)cookie->i_sortattr;
} else {
sortattr = "cn";
}
} else {
sortattr = "cn uid";
}
rc = ldap_create_sort_keylist(&sortkeylist, sortattr);
if (free_sort)
free(sortattr);
if (rc != LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER, &rc);
return (rc);
}
rc = ldap_create_sort_control(cookie->conn->ld,
sortkeylist, 1, &sortctrl);
ldap_free_sort_keylist(sortkeylist);
if (rc != LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER, &rc);
return (rc);
}
vlist.ldvlist_index = cookie->index;
vlist.ldvlist_size = 0;
vlist.ldvlist_before_count = 0;
vlist.ldvlist_after_count = LISTPAGESIZE-1;
vlist.ldvlist_attrvalue = NULL;
vlist.ldvlist_extradata = NULL;
rc = ldap_create_virtuallist_control(cookie->conn->ld,
&vlist, &vlvctrl);
if (rc != LDAP_SUCCESS) {
ldap_control_free(sortctrl);
(void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
&rc);
return (rc);
}
ctrls = (LDAPControl **)calloc(3, sizeof (LDAPControl *));
if (ctrls == NULL) {
ldap_control_free(sortctrl);
ldap_control_free(vlvctrl);
return (LDAP_NO_MEMORY);
}
ctrls[0] = sortctrl;
ctrls[1] = vlvctrl;
cookie->p_serverctrls = ctrls;
return (LDAP_SUCCESS);
}
static int
setup_simplepg_params(ns_ldap_cookie_t *cookie)
{
LDAPControl **ctrls;
LDAPControl *pgctrl = NULL;
int rc;
_freeControlList(&cookie->p_serverctrls);
rc = ldap_create_page_control(cookie->conn->ld, LISTPAGESIZE,
cookie->ctrlCookie, (char)0, &pgctrl);
if (rc != LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld, LDAP_OPT_ERROR_NUMBER,
&rc);
return (rc);
}
ctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
if (ctrls == NULL) {
ldap_control_free(pgctrl);
return (LDAP_NO_MEMORY);
}
ctrls[0] = pgctrl;
cookie->p_serverctrls = ctrls;
return (LDAP_SUCCESS);
}
static void
proc_result_referrals(ns_ldap_cookie_t *cookie)
{
int errCode, i, rc;
char **referrals = NULL;
if (cookie->refpos == NULL) {
cookie->new_state = END_RESULT;
rc = ldap_parse_result(cookie->conn->ld,
cookie->resultMsg,
&errCode, NULL,
NULL, &referrals,
NULL, 0);
if (rc != NS_LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER,
&cookie->err_rc);
cookie->new_state = LDAP_ERROR;
return;
}
if (errCode == LDAP_REFERRAL) {
for (i = 0; referrals[i] != NULL;
i++) {
rc = __s_api_addRefInfo(
&cookie->reflist,
referrals[i],
cookie->basedn,
&cookie->scope,
cookie->filter,
cookie->conn->ld);
if (rc != NS_LDAP_SUCCESS) {
cookie->new_state =
ERROR;
break;
}
}
ldap_value_free(referrals);
}
}
}
static void
proc_search_references(ns_ldap_cookie_t *cookie)
{
char **refurls = NULL;
int i, rc;
if (cookie->refpos == NULL) {
refurls = ldap_get_reference_urls(
cookie->conn->ld,
cookie->resultMsg);
if (refurls == NULL) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER,
&cookie->err_rc);
cookie->new_state = LDAP_ERROR;
return;
}
for (i = 0; refurls[i] != NULL; i++) {
rc = __s_api_addRefInfo(
&cookie->reflist,
refurls[i],
cookie->basedn,
&cookie->scope,
cookie->filter,
cookie->conn->ld);
if (rc != NS_LDAP_SUCCESS) {
cookie->new_state =
ERROR;
break;
}
}
for (i = 0; refurls[i] != NULL; i++)
free(refurls[i]);
}
}
static ns_state_t
multi_result(ns_ldap_cookie_t *cookie)
{
char errstr[MAXERROR];
char *err;
ns_ldap_error_t **errorp = NULL;
LDAPControl **retCtrls = NULL;
int i, rc;
int errCode;
boolean_t finished = B_FALSE;
unsigned long target_posp = 0;
unsigned long list_size = 0;
unsigned int count = 0;
char **referrals = NULL;
if (cookie->listType == VLVCTRLFLAG) {
rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
&errCode, NULL, NULL, &referrals, &retCtrls, 0);
if (rc != LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER,
&cookie->err_rc);
(void) sprintf(errstr,
gettext("LDAP ERROR (%d): %s.\n"),
cookie->err_rc,
gettext(ldap_err2string(cookie->err_rc)));
err = strdup(errstr);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
LDAP_ERROR);
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
return (LDAP_ERROR);
}
if (errCode == LDAP_REFERRAL) {
for (i = 0; referrals[i] != NULL;
i++) {
rc = __s_api_addRefInfo(
&cookie->reflist,
referrals[i],
cookie->basedn,
&cookie->scope,
cookie->filter,
cookie->conn->ld);
if (rc != NS_LDAP_SUCCESS) {
ldap_value_free(
referrals);
if (retCtrls)
ldap_controls_free(
retCtrls);
return (ERROR);
}
}
ldap_value_free(referrals);
if (retCtrls)
ldap_controls_free(retCtrls);
return (END_RESULT);
}
if (retCtrls) {
rc = ldap_parse_virtuallist_control(
cookie->conn->ld, retCtrls,
&target_posp, &list_size, &errCode);
if (rc == LDAP_SUCCESS) {
if (target_posp != 0 && list_size != 0) {
cookie->index =
target_posp + LISTPAGESIZE;
if (cookie->index > list_size)
finished = B_TRUE;
} else {
if (cookie->entryCount < LISTPAGESIZE)
finished = B_TRUE;
else
cookie->index +=
cookie->entryCount;
}
}
ldap_controls_free(retCtrls);
retCtrls = NULL;
} else {
finished = B_TRUE;
}
} else if (cookie->listType == SIMPLEPAGECTRLFLAG) {
rc = ldap_parse_result(cookie->conn->ld, cookie->resultMsg,
&errCode, NULL, NULL, &referrals, &retCtrls, 0);
if (rc != LDAP_SUCCESS) {
(void) ldap_get_option(cookie->conn->ld,
LDAP_OPT_ERROR_NUMBER,
&cookie->err_rc);
(void) sprintf(errstr,
gettext("LDAP ERROR (%d): %s.\n"),
cookie->err_rc,
gettext(ldap_err2string(cookie->err_rc)));
err = strdup(errstr);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
LDAP_ERROR);
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
return (LDAP_ERROR);
}
if (errCode == LDAP_REFERRAL) {
for (i = 0; referrals[i] != NULL;
i++) {
rc = __s_api_addRefInfo(
&cookie->reflist,
referrals[i],
cookie->basedn,
&cookie->scope,
cookie->filter,
cookie->conn->ld);
if (rc != NS_LDAP_SUCCESS) {
ldap_value_free(
referrals);
if (retCtrls)
ldap_controls_free(
retCtrls);
return (ERROR);
}
}
ldap_value_free(referrals);
if (retCtrls)
ldap_controls_free(retCtrls);
return (END_RESULT);
}
if (retCtrls) {
if (cookie->ctrlCookie)
ber_bvfree(cookie->ctrlCookie);
cookie->ctrlCookie = NULL;
rc = ldap_parse_page_control(
cookie->conn->ld, retCtrls,
&count, &cookie->ctrlCookie);
if (rc == LDAP_SUCCESS) {
if ((cookie->ctrlCookie == NULL) ||
(cookie->ctrlCookie->bv_val == NULL) ||
(cookie->ctrlCookie->bv_len == 0))
finished = B_TRUE;
}
ldap_controls_free(retCtrls);
retCtrls = NULL;
} else {
finished = B_TRUE;
}
}
if (!finished && cookie->listType == VLVCTRLFLAG)
return (NEXT_VLV);
if (!finished && cookie->listType == SIMPLEPAGECTRLFLAG)
return (NEXT_PAGE);
if (finished)
return (END_RESULT);
return (ERROR);
}
static void
clear_results(ns_ldap_cookie_t *cookie)
{
int rc;
if (cookie->conn != NULL && cookie->conn->ld != NULL &&
(cookie->connectionId != -1 ||
(cookie->conn_user != NULL &&
cookie->conn_user->conn_mt != NULL)) &&
cookie->msgId != 0) {
rc = ldap_result(cookie->conn->ld, cookie->msgId, LDAP_MSG_ALL,
(struct timeval *)&cookie->search_timeout,
&cookie->resultMsg);
if (rc != -1 && rc != 0 && cookie->resultMsg != NULL) {
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
}
if (rc == 0)
(void) ldap_abandon_ext(cookie->conn->ld, cookie->msgId,
NULL, NULL);
cookie->msgId = 0;
}
}
static
ns_state_t
search_state_machine(ns_ldap_cookie_t *cookie, ns_state_t state, int cycle)
{
char errstr[MAXERROR];
char *err;
int rc, ret;
int rc_save;
ns_ldap_entry_t *nextEntry;
ns_ldap_error_t *error = NULL;
ns_ldap_error_t **errorp;
struct timeval tv;
errorp = &error;
cookie->state = state;
errstr[0] = '\0';
for (;;) {
switch (cookie->state) {
case CLEAR_RESULTS:
clear_results(cookie);
cookie->new_state = EXIT;
break;
case GET_ACCT_MGMT_INFO:
cookie->nopasswd_acct_mgmt = 1;
cookie->new_state = INIT;
break;
case EXIT:
if (cookie->attribute) {
__s_api_free2dArray(cookie->attribute);
cookie->attribute = NULL;
}
if (cookie->reflist) {
__s_api_deleteRefInfo(cookie->reflist);
cookie->reflist = NULL;
}
return (EXIT);
case INIT:
cookie->sdpos = NULL;
cookie->new_state = NEXT_SEARCH_DESCRIPTOR;
if (cookie->attribute) {
__s_api_free2dArray(cookie->attribute);
cookie->attribute = NULL;
}
if ((cookie->i_flags & NS_LDAP_NOMAP) == 0 &&
cookie->i_attr) {
cookie->attribute =
__ns_ldap_mapAttributeList(
cookie->service,
cookie->i_attr);
}
break;
case REINIT:
cookie->retries++;
if (cookie->retries > NS_LIST_TRY_MAX - 1) {
cookie->new_state = LDAP_ERROR;
break;
}
if (cookie->conn_user != NULL) {
int retry;
ns_conn_mgmt_t *cmg;
cmg = cookie->conn_user->conn_mgmt;
retry = cookie->conn_user->retry;
if (cmg != NULL && cmg->cfg_reloaded == 1)
retry = 1;
if (retry == 0) {
cookie->new_state = LDAP_ERROR;
break;
}
}
if (cookie->resultMsg != NULL) {
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
}
(void) __ns_ldap_freeError(&cookie->errorp);
(void) __ns_ldap_freeResult(&cookie->result);
cookie->sdpos = cookie->sdlist;
cookie->err_from_result = 0;
cookie->err_rc = 0;
cookie->new_state = NEXT_SESSION;
break;
case NEXT_SEARCH_DESCRIPTOR:
if (cookie->sdpos == NULL) {
cookie->sdpos = cookie->sdlist;
cookie->new_state = GET_SESSION;
} else {
cookie->sdpos++;
cookie->new_state = NEXT_SEARCH;
}
if (*cookie->sdpos == NULL)
cookie->new_state = EXIT;
break;
case GET_SESSION:
if (get_current_session(cookie) < 0)
cookie->new_state = NEXT_SESSION;
else
cookie->new_state = NEXT_SEARCH;
break;
case NEXT_SESSION:
if (get_next_session(cookie) < 0)
cookie->new_state = RESTART_SESSION;
else
cookie->new_state = NEXT_SEARCH;
break;
case RESTART_SESSION:
if (cookie->i_flags & NS_LDAP_HARD) {
cookie->new_state = NEXT_SESSION;
break;
}
(void) sprintf(errstr,
gettext("Session error no available conn.\n"),
state);
err = strdup(errstr);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
LDAP_ERROR);
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
cookie->new_state = EXIT;
break;
case NEXT_SEARCH:
if (cookie->refpos) {
if (setup_referral_search(cookie) < 0) {
cookie->new_state = EXIT;
break;
}
} else if (setup_next_search(cookie) < 0) {
cookie->new_state = EXIT;
break;
}
if (paging_supported(cookie)) {
if (cookie->use_paging &&
(cookie->scope != LDAP_SCOPE_BASE)) {
cookie->index = 1;
if (cookie->listType == VLVCTRLFLAG)
cookie->new_state = NEXT_VLV;
else
cookie->new_state = NEXT_PAGE;
break;
}
}
cookie->new_state = ONE_SEARCH;
break;
case NEXT_VLV:
rc = setup_vlv_params(cookie);
if (rc != LDAP_SUCCESS) {
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
break;
}
cookie->next_state = MULTI_RESULT;
cookie->new_state = DO_SEARCH;
break;
case NEXT_PAGE:
rc = setup_simplepg_params(cookie);
if (rc != LDAP_SUCCESS) {
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
break;
}
cookie->next_state = MULTI_RESULT;
cookie->new_state = DO_SEARCH;
break;
case ONE_SEARCH:
cookie->next_state = NEXT_RESULT;
cookie->new_state = DO_SEARCH;
break;
case DO_SEARCH:
cookie->entryCount = 0;
rc = ldap_search_ext(cookie->conn->ld,
cookie->basedn,
cookie->scope,
cookie->filter,
cookie->attribute,
0,
cookie->p_serverctrls,
NULL,
&cookie->search_timeout, 0,
&cookie->msgId);
if (rc != LDAP_SUCCESS) {
if (rc == LDAP_BUSY ||
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM ||
rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) {
if (cookie->reinit_on_retriable_err) {
cookie->err_rc = rc;
cookie->new_state = REINIT;
} else {
cookie->new_state =
NEXT_SESSION;
}
if ((rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) &&
(cookie->conn_user == NULL ||
cookie->conn_user->conn_mt ==
NULL)) {
ret = __s_api_removeServer(
cookie->conn->serverAddr);
if (ret == NS_CACHE_NOSERVER &&
cookie->conn_auth_type
== NS_LDAP_AUTH_NONE) {
cookie->err_rc = rc;
cookie->new_state =
LDAP_ERROR;
}
if (cookie->connectionId > -1) {
DropConnection(
cookie->
connectionId,
NS_LDAP_NEW_CONN);
cookie->connectionId =
-1;
}
} else if ((rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) &&
cookie->conn_user != NULL) {
if (cookie->
reinit_on_retriable_err) {
__s_api_conn_mt_close(
cookie->conn_user,
rc,
&cookie->errorp);
} else {
cookie->err_rc = rc;
cookie->new_state =
LDAP_ERROR;
}
}
break;
}
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
break;
}
cookie->new_state = cookie->next_state;
break;
case NEXT_RESULT:
if (cookie->no_wait == B_TRUE)
(void) memset(&tv, 0, sizeof (tv));
else
tv = cookie->search_timeout;
rc = ldap_result(cookie->conn->ld, cookie->msgId,
LDAP_MSG_ONE,
&tv,
&cookie->resultMsg);
if (rc == LDAP_RES_SEARCH_RESULT) {
cookie->new_state = END_RESULT;
if (cookie->followRef)
proc_result_referrals(
cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
if (rc == LDAP_RES_SEARCH_REFERENCE) {
if (cookie->followRef)
proc_search_references(cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
if (rc != LDAP_RES_SEARCH_ENTRY) {
switch (rc) {
case 0:
if (cookie->no_wait == B_TRUE) {
(void) ldap_msgfree(
cookie->resultMsg);
cookie->resultMsg = NULL;
return (cookie->new_state);
}
rc = LDAP_TIMEOUT;
break;
case -1:
rc = ldap_get_lderrno(cookie->conn->ld,
NULL, NULL);
break;
default:
rc = ldap_result2error(cookie->conn->ld,
cookie->resultMsg, 1);
break;
}
if ((rc == LDAP_TIMEOUT ||
rc == LDAP_SERVER_DOWN) &&
(cookie->conn_user == NULL ||
cookie->conn_user->conn_mt == NULL)) {
if (rc == LDAP_TIMEOUT)
(void) __s_api_removeServer(
cookie->conn->serverAddr);
if (cookie->connectionId > -1) {
DropConnection(
cookie->connectionId,
NS_LDAP_NEW_CONN);
cookie->connectionId = -1;
}
cookie->err_from_result = 1;
}
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
if (rc == LDAP_BUSY ||
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM) {
if (cookie->reinit_on_retriable_err) {
cookie->err_rc = rc;
cookie->err_from_result = 1;
cookie->new_state = REINIT;
} else {
cookie->new_state =
NEXT_SESSION;
}
break;
}
if ((rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) &&
cookie->reinit_on_retriable_err) {
ns_ldap_error_t *errorp = NULL;
cookie->err_rc = rc;
cookie->err_from_result = 1;
cookie->new_state = REINIT;
if (cookie->conn_user != NULL)
__s_api_conn_mt_close(
cookie->conn_user,
rc, &errorp);
if (errorp != NULL) {
(void) __ns_ldap_freeError(
&cookie->errorp);
cookie->errorp = errorp;
}
break;
}
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
break;
}
if (cookie->nopasswd_acct_mgmt == 1) {
rc = ldap_get_entry_controls(cookie->conn->ld,
cookie->resultMsg,
&(cookie->resultctrl));
if (rc != LDAP_SUCCESS) {
cookie->new_state = LDAP_ERROR;
cookie->err_rc = rc;
break;
}
}
rc = __s_api_getEntry(cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
if (rc != NS_LDAP_SUCCESS) {
cookie->new_state = LDAP_ERROR;
break;
}
cookie->new_state = PROCESS_RESULT;
cookie->next_state = NEXT_RESULT;
break;
case MULTI_RESULT:
if (cookie->no_wait == B_TRUE)
(void) memset(&tv, 0, sizeof (tv));
else
tv = cookie->search_timeout;
rc = ldap_result(cookie->conn->ld, cookie->msgId,
LDAP_MSG_ONE,
&tv,
&cookie->resultMsg);
if (rc == LDAP_RES_SEARCH_RESULT) {
rc = ldap_result2error(cookie->conn->ld,
cookie->resultMsg, 0);
if (rc == LDAP_ADMINLIMIT_EXCEEDED &&
cookie->listType == VLVCTRLFLAG &&
cookie->sortTypeTry == SSS_SINGLE_ATTR) {
cookie->sortTypeTry = SSS_CN_UID_ATTRS;
cookie->new_state = NEXT_VLV;
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
if (rc != LDAP_SUCCESS) {
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
cookie->new_state = multi_result(cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
if (rc == LDAP_RES_SEARCH_REFERENCE &&
cookie->followRef) {
proc_search_references(cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
break;
}
if (rc != LDAP_RES_SEARCH_ENTRY) {
switch (rc) {
case 0:
if (cookie->no_wait == B_TRUE) {
(void) ldap_msgfree(
cookie->resultMsg);
cookie->resultMsg = NULL;
return (cookie->new_state);
}
rc = LDAP_TIMEOUT;
break;
case -1:
rc = ldap_get_lderrno(cookie->conn->ld,
NULL, NULL);
break;
default:
rc = ldap_result2error(cookie->conn->ld,
cookie->resultMsg, 1);
break;
}
if ((rc == LDAP_TIMEOUT ||
rc == LDAP_SERVER_DOWN) &&
(cookie->conn_user == NULL ||
cookie->conn_user->conn_mt == NULL)) {
if (rc == LDAP_TIMEOUT)
(void) __s_api_removeServer(
cookie->conn->serverAddr);
if (cookie->connectionId > -1) {
DropConnection(
cookie->connectionId,
NS_LDAP_NEW_CONN);
cookie->connectionId = -1;
}
cookie->err_from_result = 1;
}
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
if (rc == LDAP_BUSY ||
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM) {
if (cookie->reinit_on_retriable_err) {
cookie->err_rc = rc;
cookie->err_from_result = 1;
cookie->new_state = REINIT;
} else {
cookie->new_state =
NEXT_SESSION;
}
break;
}
if ((rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) &&
cookie->reinit_on_retriable_err) {
ns_ldap_error_t *errorp = NULL;
cookie->err_rc = rc;
cookie->err_from_result = 1;
cookie->new_state = REINIT;
if (cookie->conn_user != NULL)
__s_api_conn_mt_close(
cookie->conn_user,
rc, &errorp);
if (errorp != NULL) {
(void) __ns_ldap_freeError(
&cookie->errorp);
cookie->errorp = errorp;
}
break;
}
cookie->err_rc = rc;
cookie->new_state = LDAP_ERROR;
break;
}
cookie->entryCount++;
rc = __s_api_getEntry(cookie);
(void) ldap_msgfree(cookie->resultMsg);
cookie->resultMsg = NULL;
if (rc != NS_LDAP_SUCCESS) {
cookie->new_state = LDAP_ERROR;
break;
}
if (cookie->listType == VLVCTRLFLAG)
update_srvsidesort_type(cookie->service,
cookie->sortTypeTry);
cookie->new_state = PROCESS_RESULT;
cookie->next_state = MULTI_RESULT;
break;
case PROCESS_RESULT:
if (cookie->use_usercb && cookie->callback) {
rc = 0;
for (nextEntry = cookie->result->entry;
nextEntry != NULL;
nextEntry = nextEntry->next) {
rc = (*cookie->callback)(nextEntry,
cookie->userdata);
if (rc == NS_LDAP_CB_DONE) {
rc = NS_LDAP_PARTIAL;
cookie->err_rc = rc;
break;
} else if (rc != NS_LDAP_CB_NEXT) {
rc = NS_LDAP_OP_FAILED;
cookie->err_rc = rc;
break;
}
}
(void) __ns_ldap_freeResult(&cookie->result);
cookie->result = NULL;
}
if (rc != 0) {
cookie->new_state = EXIT;
break;
}
cookie->new_state = cookie->next_state;
break;
case END_PROCESS_RESULT:
cookie->new_state = cookie->next_state;
break;
case END_RESULT:
if (cookie->followRef && cookie->reflist)
cookie->new_state =
NEXT_REFERRAL;
else
cookie->new_state =
NEXT_SEARCH_DESCRIPTOR;
break;
case NEXT_REFERRAL:
if (cookie->refpos == NULL)
cookie->refpos =
cookie->reflist;
else
cookie->refpos =
cookie->refpos->next;
if (cookie->refpos != NULL) {
cookie->new_state =
GET_REFERRAL_SESSION;
} else {
__s_api_deleteRefInfo(cookie->reflist);
cookie->reflist = NULL;
cookie->new_state =
NEXT_SEARCH_DESCRIPTOR;
if (cookie->conn_user != NULL)
cookie->conn_user->referral = B_FALSE;
}
break;
case GET_REFERRAL_SESSION:
if (get_referral_session(cookie) < 0) {
cookie->new_state = EXIT;
} else {
cookie->new_state = NEXT_SEARCH;
}
break;
case LDAP_ERROR:
rc_save = cookie->err_rc;
if (cookie->err_from_result) {
if (cookie->err_rc == LDAP_SERVER_DOWN) {
(void) sprintf(errstr,
gettext("LDAP ERROR (%d): "
"Error occurred during"
" receiving results. "
"Connection to server lost."),
cookie->err_rc);
} else if (cookie->err_rc == LDAP_TIMEOUT) {
(void) sprintf(errstr,
gettext("LDAP ERROR (%d): "
"Error occurred during"
" receiving results. %s"
"."), cookie->err_rc,
ldap_err2string(
cookie->err_rc));
}
} else {
(void) sprintf(errstr,
gettext("LDAP ERROR (%d): %s."),
cookie->err_rc,
ldap_err2string(cookie->err_rc));
}
err = strdup(errstr);
if (cookie->err_from_result) {
if (cookie->err_rc == LDAP_SERVER_DOWN) {
MKERROR(LOG_INFO, *errorp,
cookie->err_rc, err,
LDAP_ERROR);
} else {
MKERROR(LOG_WARNING, *errorp,
cookie->err_rc, err,
LDAP_ERROR);
}
} else {
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL,
err, LDAP_ERROR);
}
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
if (cookie->conn_user != NULL) {
if (rc_save == LDAP_SERVER_DOWN ||
rc_save == LDAP_CONNECT_ERROR) {
__s_api_conn_mt_close(cookie->conn_user,
rc_save, &cookie->errorp);
return (ERROR);
}
}
return (ERROR);
default:
case ERROR:
(void) sprintf(errstr,
gettext("Internal State machine exit (%d).\n"),
cookie->state);
err = strdup(errstr);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err,
LDAP_ERROR);
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
return (ERROR);
}
if (cookie->conn_user != NULL &&
cookie->conn_user->bad_mt_conn == B_TRUE) {
__s_api_conn_mt_close(cookie->conn_user, 0, NULL);
cookie->err_rc = cookie->conn_user->ns_rc;
cookie->errorp = cookie->conn_user->ns_error;
cookie->conn_user->ns_error = NULL;
return (ERROR);
}
if (cycle == ONE_STEP) {
return (cookie->new_state);
}
cookie->state = cookie->new_state;
}
#if 0
(void) sprintf(errstr,
gettext("Unexpected State machine error.\n"));
err = strdup(errstr);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, err, NS_LDAP_MEMORY);
cookie->err_rc = NS_LDAP_INTERNAL;
cookie->errorp = *errorp;
return (ERROR);
#endif
}
static int
check_shadow(ns_ldap_cookie_t *cookie, const char *service)
{
char errstr[MAXERROR];
char *err;
boolean_t priv;
priv_set_t *ps;
priv_set_t *zs;
if ((strcmp(service, "shadow") == 0) &&
__ns_ldap_is_shadow_update_enabled()) {
priv = (geteuid() == 0);
if (!priv) {
ps = priv_allocset();
(void) getppriv(PRIV_EFFECTIVE, ps);
zs = priv_str_to_set("zone", ",", NULL);
priv = priv_isequalset(ps, zs);
priv_freeset(ps);
priv_freeset(zs);
}
if (!priv) {
(void) sprintf(errstr,
gettext("Permission denied"));
err = strdup(errstr);
if (err == NULL)
return (NS_LDAP_MEMORY);
MKERROR(LOG_INFO, cookie->errorp, NS_LDAP_INTERNAL, err,
NS_LDAP_MEMORY);
return (NS_LDAP_INTERNAL);
}
cookie->i_flags |= NS_LDAP_READ_SHADOW;
if (cookie->i_flags & NS_LDAP_KEEP_CONN)
return (NS_LDAP_INVALID_PARAM);
cookie->i_flags |= NS_LDAP_NEW_CONN;
}
return (NS_LDAP_SUCCESS);
}
static int
ldap_list(
ns_ldap_list_batch_t *batch,
const char *service,
const char *filter,
const char *sortattr,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
ns_ldap_result_t **rResult,
ns_ldap_error_t **errorp,
int *rcp,
int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
const void *userdata, ns_conn_user_t *conn_user)
{
ns_ldap_cookie_t *cookie;
ns_ldap_search_desc_t **sdlist = NULL;
ns_ldap_search_desc_t *dptr;
ns_ldap_error_t *error = NULL;
char **dns = NULL;
int scope;
int rc;
int from_result;
*errorp = NULL;
*rResult = NULL;
*rcp = NS_LDAP_SUCCESS;
if (flags & NS_LDAP_READ_SHADOW)
return (NS_LDAP_INVALID_PARAM);
cookie = init_search_state_machine();
if (cookie == NULL) {
*rcp = NS_LDAP_MEMORY;
return (NS_LDAP_MEMORY);
}
cookie->conn_user = conn_user;
rc = __s_api_toFollowReferrals(flags,
&cookie->followRef, errorp);
if (rc != NS_LDAP_SUCCESS) {
delete_search_cookie(cookie);
*rcp = rc;
return (rc);
}
rc = __s_api_get_SSD_from_SSDtoUse_service(service,
&sdlist, &error);
if (rc != NS_LDAP_SUCCESS) {
delete_search_cookie(cookie);
*errorp = error;
*rcp = rc;
return (rc);
}
if (sdlist == NULL) {
sdlist = (ns_ldap_search_desc_t **)calloc(2,
sizeof (ns_ldap_search_desc_t *));
if (sdlist == NULL) {
delete_search_cookie(cookie);
cookie = NULL;
*rcp = NS_LDAP_MEMORY;
return (NS_LDAP_MEMORY);
}
dptr = (ns_ldap_search_desc_t *)
calloc(1, sizeof (ns_ldap_search_desc_t));
if (dptr == NULL) {
free(sdlist);
delete_search_cookie(cookie);
cookie = NULL;
*rcp = NS_LDAP_MEMORY;
return (NS_LDAP_MEMORY);
}
sdlist[0] = dptr;
rc = __s_api_getDNs(&dns, service, &cookie->errorp);
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
__s_api_free2dArray(dns);
dns = NULL;
}
*errorp = cookie->errorp;
cookie->errorp = NULL;
delete_search_cookie(cookie);
cookie = NULL;
*rcp = rc;
return (rc);
}
dptr->basedn = strdup(dns[0]);
__s_api_free2dArray(dns);
dns = NULL;
scope = 0;
rc = __s_api_getSearchScope(&scope, &cookie->errorp);
dptr->scope = scope;
}
cookie->sdlist = sdlist;
if (flags & NS_LDAP_PAGE_CTRL)
cookie->use_paging = TRUE;
else
cookie->use_paging = FALSE;
cookie->userdata = userdata;
if (init_filter_cb != NULL) {
cookie->init_filter_cb = init_filter_cb;
cookie->use_filtercb = 1;
}
if (callback != NULL) {
cookie->callback = callback;
cookie->use_usercb = 1;
}
cookie->i_flags = flags;
if (service) {
cookie->service = strdup(service);
if (cookie->service == NULL) {
delete_search_cookie(cookie);
cookie = NULL;
*rcp = NS_LDAP_MEMORY;
return (NS_LDAP_MEMORY);
}
if (auth == NULL) {
rc = check_shadow(cookie, service);
if (rc != NS_LDAP_SUCCESS) {
*errorp = cookie->errorp;
cookie->errorp = NULL;
delete_search_cookie(cookie);
cookie = NULL;
*rcp = rc;
return (rc);
}
}
}
cookie->i_filter = strdup(filter);
cookie->i_attr = attribute;
cookie->i_auth = auth;
cookie->i_sortattr = sortattr;
if (batch != NULL) {
cookie->batch = batch;
cookie->reinit_on_retriable_err = B_TRUE;
cookie->no_wait = B_TRUE;
(void) search_state_machine(cookie, INIT, 0);
cookie->no_wait = B_FALSE;
rc = cookie->err_rc;
if (rc == NS_LDAP_SUCCESS) {
cookie->caller_result = rResult;
cookie->caller_errorp = errorp;
cookie->caller_rc = rcp;
cookie->next_cookie_in_batch = batch->cookie_list;
batch->cookie_list = cookie;
batch->nactive++;
return (rc);
}
} else {
(void) search_state_machine(cookie, INIT, 0);
}
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS) {
if (conn_user != NULL && conn_user->ns_error != NULL) {
*errorp = conn_user->ns_error;
conn_user->ns_error = NULL;
} else {
*errorp = cookie->errorp;
}
}
*rResult = cookie->result;
from_result = cookie->err_from_result;
cookie->errorp = NULL;
cookie->result = NULL;
delete_search_cookie(cookie);
cookie = NULL;
if (from_result == 0 && *rResult == NULL)
rc = NS_LDAP_NOTFOUND;
*rcp = rc;
return (rc);
}
int
__ns_ldap_list(
const char *service,
const char *filter,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
ns_ldap_result_t **rResult,
ns_ldap_error_t **errorp,
int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
const void *userdata)
{
int mod_flags;
mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
return (__ns_ldap_list_sort(service, filter, NULL, init_filter_cb,
attribute, auth, mod_flags, rResult, errorp,
callback, userdata));
}
int
__ns_ldap_list_sort(
const char *service,
const char *filter,
const char *sortattr,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
ns_ldap_result_t **rResult,
ns_ldap_error_t **errorp,
int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
const void *userdata)
{
ns_conn_user_t *cu = NULL;
int try_cnt = 0;
int rc = NS_LDAP_SUCCESS, trc;
for (;;) {
if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
&try_cnt, &rc, errorp) == 0)
break;
rc = ldap_list(NULL, service, filter, sortattr, init_filter_cb,
attribute, auth, flags, rResult, errorp, &trc, callback,
userdata, cu);
}
return (rc);
}
int
__ns_ldap_list_batch_start(ns_ldap_list_batch_t **batch)
{
*batch = calloc(1, sizeof (ns_ldap_list_batch_t));
if (*batch == NULL)
return (NS_LDAP_MEMORY);
return (NS_LDAP_SUCCESS);
}
int
__ns_ldap_list_batch_add(
ns_ldap_list_batch_t *batch,
const char *service,
const char *filter,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
ns_ldap_result_t **rResult,
ns_ldap_error_t **errorp,
int *rcp,
int (*callback)(const ns_ldap_entry_t *entry, const void *userdata),
const void *userdata)
{
ns_conn_user_t *cu;
int rc;
int mod_flags;
cu = __s_api_conn_user_init(NS_CONN_USER_SEARCH, NULL, 0);
if (cu == NULL) {
if (rcp != NULL)
*rcp = NS_LDAP_MEMORY;
return (NS_LDAP_MEMORY);
}
mod_flags = flags & (~NS_LDAP_PAGE_CTRL);
rc = ldap_list(batch, service, filter, NULL, init_filter_cb, attribute,
auth, mod_flags, rResult, errorp, rcp, callback, userdata, cu);
if (rc != NS_LDAP_SUCCESS && cu != NULL) {
if (cu->conn_mt != NULL)
__s_api_conn_mt_return(cu);
__s_api_conn_user_free(cu);
}
return (rc);
}
void
__ns_ldap_list_batch_release(ns_ldap_list_batch_t *batch)
{
ns_ldap_cookie_t *c, *next;
for (c = batch->cookie_list; c != NULL; c = next) {
next = c->next_cookie_in_batch;
if (c->conn_user != NULL) {
if (c->conn_user->conn_mt != NULL)
__s_api_conn_mt_return(c->conn_user);
__s_api_conn_user_free(c->conn_user);
c->conn_user = NULL;
}
delete_search_cookie(c);
}
free(batch);
}
#define LD_USING_STATE(st) \
((st == DO_SEARCH) || (st == MULTI_RESULT) || (st == NEXT_RESULT))
static
int
__ns_ldap_list_batch_process(ns_ldap_list_batch_t *batch, int *rcp)
{
ns_ldap_cookie_t *c, *ptr, **prev;
ns_state_t state;
ns_ldap_error_t *errorp = NULL;
int rc;
if (batch->nactive == 0)
return (0);
c = (batch->next_cookie == NULL) ?
batch->cookie_list : batch->next_cookie;
batch->next_cookie = c->next_cookie_in_batch;
if (LD_USING_STATE(c->new_state) && c->conn_user != NULL) {
rc = __s_api_setup_getnext(c->conn_user, &c->err_rc, &errorp);
if (rc == LDAP_BUSY || rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM) {
if (errorp != NULL) {
(void) __ns_ldap_freeError(&c->errorp);
c->errorp = errorp;
}
c->new_state = REINIT;
} else if (rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) {
if (errorp != NULL) {
(void) __ns_ldap_freeError(&c->errorp);
c->errorp = errorp;
}
c->new_state = REINIT;
__s_api_conn_mt_close(
c->conn_user, rc, NULL);
} else if (rc != NS_LDAP_SUCCESS) {
if (rcp != NULL)
*rcp = rc;
*c->caller_result = NULL;
*c->caller_errorp = errorp;
*c->caller_rc = rc;
return (-1);
}
}
for (;;) {
state = search_state_machine(c, c->new_state, ONE_STEP);
switch (state) {
case LDAP_ERROR:
(void) search_state_machine(c, state, ONE_STEP);
(void) search_state_machine(c, CLEAR_RESULTS, ONE_STEP);
case ERROR:
case EXIT:
*c->caller_result = c->result;
*c->caller_errorp = c->errorp;
*c->caller_rc =
(c->result == NULL && c->err_from_result == 0)
? NS_LDAP_NOTFOUND : c->err_rc;
c->result = NULL;
c->errorp = NULL;
ptr = batch->cookie_list;
prev = &batch->cookie_list;
while (ptr != NULL) {
if (ptr == c) {
*prev = ptr->next_cookie_in_batch;
break;
}
prev = &ptr->next_cookie_in_batch;
ptr = ptr->next_cookie_in_batch;
}
if (c->conn_user != NULL) {
if (c->conn_user->conn_mt != NULL)
__s_api_conn_mt_return(c->conn_user);
__s_api_conn_user_free(c->conn_user);
c->conn_user = NULL;
}
delete_search_cookie(c);
batch->nactive--;
break;
case NEXT_RESULT:
case MULTI_RESULT:
break;
default:
continue;
}
break;
}
return ((batch->nactive > 0) ? 1 : 0);
}
int
__ns_ldap_list_batch_end(ns_ldap_list_batch_t *batch)
{
int rc = NS_LDAP_SUCCESS;
while (__ns_ldap_list_batch_process(batch, &rc) > 0)
;
__ns_ldap_list_batch_release(batch);
return (rc);
}
typedef struct lookup_data {
const char *lkd_dn;
const char *lkd_service;
const char *lkd_filter;
const ns_cred_t *lkd_cred;
ns_conn_user_t *lkd_user;
} lookup_data_t;
static int
lookup_create_ssd(lookup_data_t *dn_data, ns_ldap_search_desc_t **descpp)
{
ns_ldap_search_desc_t *dptr;
*descpp = NULL;
dptr = calloc(1, sizeof (ns_ldap_search_desc_t));
if (dptr == NULL)
return (NS_LDAP_MEMORY);
dptr->basedn = strdup(dn_data->lkd_dn);
dptr->scope = NS_LDAP_SCOPE_BASE;
dptr->filter = strdup(dn_data->lkd_filter);
if (dptr->basedn == NULL || dptr->filter == NULL) {
__ns_ldap_freeASearchDesc(dptr);
return (NS_LDAP_MEMORY);
}
*descpp = dptr;
return (NS_LDAP_SUCCESS);
}
static int
lookup_dn(lookup_data_t *dn_data, const char **attrs,
ns_ldap_result_t **resultp, ns_ldap_error_t **errorp)
{
ns_ldap_cookie_t *cookie;
int rc = 0;
int flags = 0;
*errorp = NULL;
*resultp = NULL;
if (dn_data == NULL || dn_data->lkd_dn == NULL ||
dn_data->lkd_dn[0] == '\0' || dn_data->lkd_filter == NULL)
return (NS_LDAP_INVALID_PARAM);
cookie = init_search_state_machine();
if (cookie == NULL)
return (NS_LDAP_MEMORY);
rc = __s_api_toFollowReferrals(flags, &cookie->followRef, errorp);
if (rc != NS_LDAP_SUCCESS)
goto out;
cookie->sdlist = calloc(2, sizeof (ns_ldap_search_desc_t *));
if (cookie->sdlist == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
rc = lookup_create_ssd(dn_data, &cookie->sdlist[0]);
if (rc != NS_LDAP_SUCCESS)
goto out;
if (dn_data->lkd_service != NULL) {
cookie->service = strdup(dn_data->lkd_service);
if (cookie->service == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
}
cookie->i_attr = attrs;
cookie->i_auth = dn_data->lkd_cred;
cookie->i_flags = 0;
cookie->i_filter = strdup(dn_data->lkd_filter);
if (cookie->i_filter == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
(void) search_state_machine(cookie, INIT, 0);
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS) {
ns_conn_user_t *user = dn_data->lkd_user;
if (user != NULL && user->ns_error != NULL) {
*errorp = user->ns_error;
user->ns_error = NULL;
} else {
*errorp = cookie->errorp;
cookie->errorp = NULL;
}
} else if (cookie->result != NULL) {
*resultp = cookie->result;
cookie->result = NULL;
} else {
rc = NS_LDAP_NOTFOUND;
}
out:
delete_search_cookie(cookie);
return (rc);
}
static int
find_domainname(const char *dn, char **domainname, const ns_cred_t *cred,
ns_ldap_error_t **errorp, ns_conn_user_t *conn_user)
{
lookup_data_t ldata;
ns_ldap_result_t *result;
char **value;
int rc;
*domainname = NULL;
*errorp = NULL;
ldata.lkd_dn = dn;
ldata.lkd_service = NULL;
ldata.lkd_filter = _NIS_FILTER;
ldata.lkd_cred = cred;
ldata.lkd_user = conn_user;
rc = lookup_dn(&ldata, nis_domain_attrs, &result, errorp);
if (rc != NS_LDAP_SUCCESS)
return (rc);
value = __ns_ldap_getAttr(result->entry, _NIS_DOMAIN);
if (value != NULL && value[0] != NULL) {
*domainname = strdup(value[0]);
if (*domainname == NULL)
rc = NS_LDAP_MEMORY;
} else {
rc = NS_LDAP_NOTFOUND;
}
(void) __ns_ldap_freeResult(&result);
return (rc);
}
static int
__s_api_find_domainname(const char *dn, char **domainname,
const ns_cred_t *cred, ns_ldap_error_t **errorp)
{
ns_conn_user_t *cu = NULL;
int try_cnt = 0;
int rc = NS_LDAP_SUCCESS;
for (;;) {
if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
&try_cnt, &rc, errorp) == 0)
break;
rc = find_domainname(dn, domainname, cred, errorp, cu);
}
return (rc);
}
static int
firstEntry(
const char *service,
const char *filter,
const char *sortattr,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
void **vcookie,
ns_ldap_result_t **result,
ns_ldap_error_t ** errorp,
const void *userdata,
ns_conn_user_t *conn_user)
{
ns_ldap_cookie_t *cookie = NULL;
ns_ldap_error_t *error = NULL;
ns_state_t state;
ns_ldap_search_desc_t **sdlist;
ns_ldap_search_desc_t *dptr;
char **dns = NULL;
int scope;
int rc;
*errorp = NULL;
*result = NULL;
if (flags & NS_LDAP_READ_SHADOW)
return (NS_LDAP_INVALID_PARAM);
rc = __s_api_get_SSD_from_SSDtoUse_service(service,
&sdlist, &error);
if (rc != NS_LDAP_SUCCESS) {
*errorp = error;
return (rc);
}
if (sdlist == NULL) {
sdlist = (ns_ldap_search_desc_t **)calloc(2,
sizeof (ns_ldap_search_desc_t *));
if (sdlist == NULL) {
return (NS_LDAP_MEMORY);
}
dptr = (ns_ldap_search_desc_t *)
calloc(1, sizeof (ns_ldap_search_desc_t));
if (dptr == NULL) {
free(sdlist);
return (NS_LDAP_MEMORY);
}
sdlist[0] = dptr;
rc = __s_api_getDNs(&dns, service, &error);
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
__s_api_free2dArray(dns);
dns = NULL;
}
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(
&sdlist);
sdlist = NULL;
}
*errorp = error;
return (rc);
}
dptr->basedn = strdup(dns[0]);
__s_api_free2dArray(dns);
dns = NULL;
scope = 0;
cookie = init_search_state_machine();
if (cookie == NULL) {
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(&sdlist);
sdlist = NULL;
}
return (NS_LDAP_MEMORY);
}
rc = __s_api_getSearchScope(&scope, &cookie->errorp);
dptr->scope = scope;
}
if (cookie == NULL)
cookie = init_search_state_machine();
if (cookie == NULL) {
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(&sdlist);
sdlist = NULL;
}
return (NS_LDAP_MEMORY);
}
cookie->conn_user = conn_user;
cookie->sdlist = sdlist;
rc = __s_api_toFollowReferrals(flags,
&cookie->followRef, errorp);
if (rc != NS_LDAP_SUCCESS) {
delete_search_cookie(cookie);
return (rc);
}
if (flags & NS_LDAP_NO_PAGE_CTRL)
cookie->use_paging = FALSE;
else
cookie->use_paging = TRUE;
cookie->userdata = userdata;
if (init_filter_cb != NULL) {
cookie->init_filter_cb = init_filter_cb;
cookie->use_filtercb = 1;
}
cookie->use_usercb = 0;
cookie->i_flags = flags;
if (service) {
cookie->service = strdup(service);
if (cookie->service == NULL) {
delete_search_cookie(cookie);
return (NS_LDAP_MEMORY);
}
if (auth == NULL) {
rc = check_shadow(cookie, service);
if (rc != NS_LDAP_SUCCESS) {
*errorp = cookie->errorp;
cookie->errorp = NULL;
delete_search_cookie(cookie);
cookie = NULL;
return (rc);
}
}
}
cookie->i_filter = strdup(filter);
cookie->i_attr = attribute;
cookie->i_sortattr = sortattr;
cookie->i_auth = auth;
state = INIT;
for (;;) {
state = search_state_machine(cookie, state, ONE_STEP);
switch (state) {
case PROCESS_RESULT:
*result = cookie->result;
cookie->result = NULL;
*vcookie = (void *)cookie;
return (NS_LDAP_SUCCESS);
case LDAP_ERROR:
state = search_state_machine(cookie, state, ONE_STEP);
state = search_state_machine(cookie, CLEAR_RESULTS,
ONE_STEP);
case ERROR:
rc = cookie->err_rc;
if (conn_user != NULL && conn_user->ns_error != NULL) {
*errorp = conn_user->ns_error;
conn_user->ns_error = NULL;
} else {
*errorp = cookie->errorp;
cookie->errorp = NULL;
}
delete_search_cookie(cookie);
return (rc);
case EXIT:
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS) {
*errorp = cookie->errorp;
cookie->errorp = NULL;
} else {
rc = NS_LDAP_NOTFOUND;
}
delete_search_cookie(cookie);
return (rc);
default:
break;
}
}
}
int
__ns_ldap_firstEntry(
const char *service,
const char *filter,
const char *vlv_sort,
int (*init_filter_cb)(const ns_ldap_search_desc_t *desc,
char **realfilter, const void *userdata),
const char * const *attribute,
const ns_cred_t *auth,
const int flags,
void **vcookie,
ns_ldap_result_t **result,
ns_ldap_error_t ** errorp,
const void *userdata)
{
ns_conn_user_t *cu = NULL;
int try_cnt = 0;
int rc = NS_LDAP_SUCCESS;
for (;;) {
if (__s_api_setup_retry_search(&cu, NS_CONN_USER_GETENT,
&try_cnt, &rc, errorp) == 0)
break;
rc = firstEntry(service, filter, vlv_sort, init_filter_cb,
attribute, auth, flags, vcookie, result, errorp, userdata,
cu);
}
return (rc);
}
int
__ns_ldap_nextEntry(void *vcookie, ns_ldap_result_t **result,
ns_ldap_error_t ** errorp)
{
ns_ldap_cookie_t *cookie;
ns_state_t state;
int rc;
cookie = (ns_ldap_cookie_t *)vcookie;
cookie->result = NULL;
*result = NULL;
if (cookie->conn_user != NULL) {
rc = __s_api_setup_getnext(cookie->conn_user,
&cookie->err_rc, errorp);
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
state = END_PROCESS_RESULT;
for (;;) {
state = search_state_machine(cookie, state, ONE_STEP);
switch (state) {
case PROCESS_RESULT:
*result = cookie->result;
cookie->result = NULL;
return (NS_LDAP_SUCCESS);
case LDAP_ERROR:
state = search_state_machine(cookie, state, ONE_STEP);
state = search_state_machine(cookie, CLEAR_RESULTS,
ONE_STEP);
case ERROR:
rc = cookie->err_rc;
*errorp = cookie->errorp;
cookie->errorp = NULL;
return (rc);
case EXIT:
return (NS_LDAP_SUCCESS);
}
}
}
int
__ns_ldap_endEntry(
void **vcookie,
ns_ldap_error_t ** errorp)
{
ns_ldap_cookie_t *cookie;
int rc;
if (*vcookie == NULL)
return (NS_LDAP_INVALID_PARAM);
cookie = (ns_ldap_cookie_t *)(*vcookie);
cookie->result = NULL;
rc = search_state_machine(cookie, CLEAR_RESULTS, 0);
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS)
*errorp = cookie->errorp;
cookie->errorp = NULL;
if (cookie->conn_user != NULL) {
if (cookie->conn_user->conn_mt != NULL)
__s_api_conn_mt_return(cookie->conn_user);
__s_api_conn_user_free(cookie->conn_user);
}
delete_search_cookie(cookie);
cookie = NULL;
*vcookie = NULL;
return (rc);
}
int
__ns_ldap_freeResult(ns_ldap_result_t **result)
{
ns_ldap_entry_t *curEntry = NULL;
ns_ldap_entry_t *delEntry = NULL;
int i;
ns_ldap_result_t *res = *result;
#ifdef DEBUG
(void) fprintf(stderr, "__ns_ldap_freeResult START\n");
#endif
if (res == NULL)
return (NS_LDAP_INVALID_PARAM);
if (res->entry != NULL)
curEntry = res->entry;
for (i = 0; i < res->entries_count; i++) {
if (curEntry != NULL) {
delEntry = curEntry;
curEntry = curEntry->next;
__ns_ldap_freeEntry(delEntry);
}
}
free(res);
*result = NULL;
return (NS_LDAP_SUCCESS);
}
int
__ns_ldap_auth(const ns_cred_t *auth, const int flags, ns_ldap_error_t **errorp,
LDAPControl **serverctrls __unused, LDAPControl **clientctrls __unused)
{
ConnectionID connectionId = -1;
Connection *conp;
int rc = 0;
int do_not_fail_if_new_pwd_reqd = 0;
int nopasswd_acct_mgmt = 0;
ns_conn_user_t *conn_user;
#ifdef DEBUG
(void) fprintf(stderr, "__ns_ldap_auth START\n");
#endif
*errorp = NULL;
if (auth == NULL)
return (NS_LDAP_INVALID_PARAM);
conn_user = __s_api_conn_user_init(NS_CONN_USER_AUTH,
NULL, B_FALSE);
rc = __s_api_getConnection(NULL, flags | NS_LDAP_NEW_CONN,
auth, &connectionId, &conp, errorp,
do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
conn_user);
if (conn_user != NULL)
__s_api_conn_user_free(conn_user);
if (rc == NS_LDAP_OP_FAILED && *errorp)
(void) __ns_ldap_freeError(errorp);
if (connectionId > -1)
DropConnection(connectionId, flags);
return (rc);
}
char **
__ns_ldap_getAttr(const ns_ldap_entry_t *entry, const char *attrname)
{
int i;
if (entry == NULL)
return (NULL);
for (i = 0; i < entry->attr_count; i++) {
if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == 0)
return (entry->attr_pair[i]->attrvalue);
}
return (NULL);
}
ns_ldap_attr_t *
__ns_ldap_getAttrStruct(const ns_ldap_entry_t *entry, const char *attrname)
{
int i;
if (entry == NULL)
return (NULL);
for (i = 0; i < entry->attr_count; i++) {
if (strcasecmp(entry->attr_pair[i]->attrname, attrname) == 0)
return (entry->attr_pair[i]);
}
return (NULL);
}
int
__ns_ldap_uid2dn(const char *uid, char **userDN, const ns_cred_t *cred,
ns_ldap_error_t **errorp)
{
ns_ldap_result_t *result = NULL;
char *filter, *userdata;
char errstr[MAXERROR];
char **value;
int rc = 0;
int i;
size_t len;
*errorp = NULL;
*userDN = NULL;
if ((uid == NULL) || (uid[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
for (i = 0; uid[i] != '\0'; i++) {
if (uid[i] == '=') {
*userDN = strdup(uid);
return (NS_LDAP_SUCCESS);
}
}
for (i = 0; (uid[i] != '\0') && isdigit(uid[i]); i++)
;
if (uid[i] == '\0') {
len = strlen(UIDNUMFILTER) + strlen(uid) + 1;
filter = malloc(len);
if (filter == NULL) {
*userDN = NULL;
return (NS_LDAP_MEMORY);
}
(void) snprintf(filter, len, UIDNUMFILTER, uid);
len = strlen(UIDNUMFILTER_SSD) + strlen(uid) + 1;
userdata = malloc(len);
if (userdata == NULL) {
*userDN = NULL;
free(filter);
return (NS_LDAP_MEMORY);
}
(void) snprintf(userdata, len, UIDNUMFILTER_SSD, uid);
} else {
len = strlen(UIDFILTER) + strlen(uid) + 1;
filter = malloc(len);
if (filter == NULL) {
*userDN = NULL;
return (NS_LDAP_MEMORY);
}
(void) snprintf(filter, len, UIDFILTER, uid);
len = strlen(UIDFILTER_SSD) + strlen(uid) + 1;
userdata = malloc(len);
if (userdata == NULL) {
*userDN = NULL;
free(filter);
return (NS_LDAP_MEMORY);
}
(void) snprintf(userdata, len, UIDFILTER_SSD, uid);
}
rc = __ns_ldap_list("passwd", filter,
__s_api_merge_SSD_filter,
NULL, cred, NS_LDAP_NOT_CVT_DN,
&result, errorp, NULL,
userdata);
free(filter);
filter = NULL;
free(userdata);
userdata = NULL;
if (rc != NS_LDAP_SUCCESS) {
if (result) {
(void) __ns_ldap_freeResult(&result);
result = NULL;
}
return (rc);
}
if (result->entries_count > 1) {
(void) __ns_ldap_freeResult(&result);
result = NULL;
*userDN = NULL;
(void) sprintf(errstr,
gettext("Too many entries are returned for %s"), uid);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
NS_LDAP_MEMORY);
return (NS_LDAP_INTERNAL);
}
value = __ns_ldap_getAttr(result->entry, "dn");
*userDN = strdup(value[0]);
(void) __ns_ldap_freeResult(&result);
result = NULL;
return (NS_LDAP_SUCCESS);
}
#define _P_UID "uid"
static const char *dn2uid_attrs[] = {
_P_CN,
_P_UID,
(char *)NULL
};
int
__ns_ldap_dn2uid(const char *dn, char **userIDp, const ns_cred_t *cred,
ns_ldap_error_t **errorp)
{
lookup_data_t ldata;
ns_ldap_result_t *result;
char **value;
int rc;
*errorp = NULL;
*userIDp = NULL;
if ((dn == NULL) || (dn[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
ldata.lkd_dn = dn;
ldata.lkd_service = "passwd";
ldata.lkd_filter = UIDDNFILTER;
ldata.lkd_cred = cred;
ldata.lkd_user = NULL;
rc = lookup_dn(&ldata, dn2uid_attrs, &result, errorp);
if (rc != NS_LDAP_SUCCESS)
return (rc);
value = __ns_ldap_getAttr(result->entry, _P_UID);
if (value != NULL && value[0] != NULL) {
*userIDp = strdup(value[0]);
if (*userIDp == NULL)
rc = NS_LDAP_MEMORY;
} else {
rc = NS_LDAP_NOTFOUND;
}
(void) __ns_ldap_freeResult(&result);
return (rc);
}
int
__ns_ldap_host2dn(const char *host, const char *domain, char **hostDN,
const ns_cred_t *cred, ns_ldap_error_t **errorp)
{
ns_ldap_result_t *result = NULL;
char *filter, *userdata;
char errstr[MAXERROR];
char **value;
int rc;
size_t len;
*errorp = NULL;
*hostDN = NULL;
if ((host == NULL) || (host[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
len = strlen(HOSTFILTER) + strlen(host) + 1;
filter = malloc(len);
if (filter == NULL) {
return (NS_LDAP_MEMORY);
}
(void) snprintf(filter, len, HOSTFILTER, host);
len = strlen(HOSTFILTER_SSD) + strlen(host) + 1;
userdata = malloc(len);
if (userdata == NULL) {
free(filter);
return (NS_LDAP_MEMORY);
}
(void) snprintf(userdata, len, HOSTFILTER_SSD, host);
rc = __ns_ldap_list("hosts", filter,
__s_api_merge_SSD_filter,
NULL, cred, NS_LDAP_NOT_CVT_DN, &result,
errorp, NULL,
userdata);
free(filter);
filter = NULL;
free(userdata);
userdata = NULL;
if (rc != NS_LDAP_SUCCESS) {
if (result) {
(void) __ns_ldap_freeResult(&result);
result = NULL;
}
return (rc);
}
if (result->entries_count > 1) {
(void) __ns_ldap_freeResult(&result);
result = NULL;
*hostDN = NULL;
(void) sprintf(errstr,
gettext("Too many entries are returned for %s"), host);
MKERROR(LOG_WARNING, *errorp, NS_LDAP_INTERNAL, strdup(errstr),
NS_LDAP_MEMORY);
return (NS_LDAP_INTERNAL);
}
value = __ns_ldap_getAttr(result->entry, "dn");
*hostDN = strdup(value[0]);
(void) __ns_ldap_freeResult(&result);
result = NULL;
return (NS_LDAP_SUCCESS);
}
int
__ns_ldap_dn2domain(const char *dn, char **domain, const ns_cred_t *cred,
ns_ldap_error_t **errorp)
{
int rc, pnum, i, j, len = 0;
char *newdn, **rdns = NULL;
char **dns, *dn1;
*errorp = NULL;
if (domain == NULL)
return (NS_LDAP_INVALID_PARAM);
else
*domain = NULL;
if ((dn == NULL) || (dn[0] == '\0'))
return (NS_LDAP_INVALID_PARAM);
dn1 = strdup(dn);
if (dn1 == NULL)
return (NS_LDAP_MEMORY);
rdns = ldap_explode_dn(dn1, 0);
free(dn1);
if (rdns == NULL || *rdns == NULL)
return (NS_LDAP_INVALID_PARAM);
for (i = 0; rdns[i]; i++)
len += strlen(rdns[i]) + 1;
pnum = i;
newdn = (char *)malloc(len + 1);
dns = (char **)calloc(pnum, sizeof (char *));
if (newdn == NULL || dns == NULL) {
if (newdn)
free(newdn);
ldap_value_free(rdns);
return (NS_LDAP_MEMORY);
}
*newdn = '\0';
for (i = 0; rdns[i]; i++) {
dns[i] = newdn + strlen(newdn);
(void) strcat(newdn,
__s_api_remove_rdn_space(rdns[i]));
(void) strcat(newdn, ",");
}
newdn[strlen(newdn) - 1] = '\0';
ldap_value_free(rdns);
for (i = 0; i < pnum; i++) {
if (*errorp)
(void) __ns_ldap_freeError(errorp);
rc = __s_api_get_cachemgr_data(NS_CACHE_DN2DOMAIN,
dns[i], domain);
if (rc != NS_LDAP_SUCCESS) {
rc = __s_api_find_domainname(dns[i], domain,
cred, errorp);
} else {
i--;
}
if (rc == NS_LDAP_SUCCESS) {
if (__s_api_nscd_proc()) {
for (j = 0; j <= i; j++) {
(void) __s_api_set_cachemgr_data(
NS_CACHE_DN2DOMAIN,
dns[j],
*domain);
}
}
break;
}
}
free(dns);
free(newdn);
if (rc != NS_LDAP_SUCCESS)
rc = NS_LDAP_NOTFOUND;
return (rc);
}
int
__ns_ldap_getServiceAuthMethods(const char *service, ns_auth_t ***auth,
ns_ldap_error_t **errorp)
{
char errstr[MAXERROR];
int rc, i;
boolean_t done = B_FALSE;
int slen;
void **param;
char **sam, *srv, *send;
ns_auth_t **authpp = NULL, *ap;
int cnt, max;
ns_config_t *cfg;
ns_ldap_error_t *error = NULL;
if (errorp == NULL)
return (NS_LDAP_INVALID_PARAM);
*errorp = NULL;
if ((service == NULL) || (service[0] == '\0') ||
(auth == NULL))
return (NS_LDAP_INVALID_PARAM);
*auth = NULL;
rc = __ns_ldap_getParam(NS_LDAP_SERVICE_AUTH_METHOD_P, ¶m, &error);
if (rc != NS_LDAP_SUCCESS || param == NULL) {
*errorp = error;
return (rc);
}
sam = (char **)param;
cfg = __s_api_get_default_config();
cnt = 0;
slen = strlen(service);
for (; *sam; sam++) {
srv = *sam;
if (strncasecmp(service, srv, slen) != 0)
continue;
srv += slen;
if (*srv != COLONTOK)
continue;
send = srv;
srv++;
for (max = 1; (send = strchr(++send, SEMITOK)) != NULL; max++)
;
authpp = (ns_auth_t **)calloc(++max, sizeof (ns_auth_t *));
if (authpp == NULL) {
(void) __ns_ldap_freeParam(¶m);
__s_api_release_config(cfg);
return (NS_LDAP_MEMORY);
}
while (!done) {
send = strchr(srv, SEMITOK);
if (send != NULL) {
*send = '\0';
send++;
}
i = __s_get_enum_value(cfg, srv, NS_LDAP_AUTH_P);
if (i == -1) {
(void) __ns_ldap_freeParam(¶m);
(void) sprintf(errstr,
gettext("Unsupported "
"serviceAuthenticationMethod: %s.\n"), srv);
MKERROR(LOG_WARNING, *errorp, NS_CONFIG_SYNTAX,
strdup(errstr), NS_LDAP_MEMORY);
__s_api_release_config(cfg);
return (NS_LDAP_CONFIG);
}
ap = __s_api_AuthEnumtoStruct((EnumAuthType_t)i);
if (ap == NULL) {
(void) __ns_ldap_freeParam(¶m);
__s_api_release_config(cfg);
return (NS_LDAP_MEMORY);
}
authpp[cnt++] = ap;
if (send == NULL)
done = B_TRUE;
else
srv = send;
}
}
*auth = authpp;
(void) __ns_ldap_freeParam(¶m);
__s_api_release_config(cfg);
return (NS_LDAP_SUCCESS);
}
int
__s_api_convert_automountmapname(const char *service, char **dn,
ns_ldap_error_t **errp)
{
char **mapping = NULL;
char *mapped_attr = NULL;
char *automountmapname = "automountMapName";
char *buffer = NULL;
int rc = NS_LDAP_SUCCESS;
char errstr[MAXERROR];
if (service == NULL || dn == NULL || *dn == NULL)
return (NS_LDAP_INVALID_PARAM);
mapping = __ns_ldap_getMappedAttributes(service, automountmapname);
if (mapping == NULL) {
mapping = __ns_ldap_getMappedAttributes(
"automount", automountmapname);
}
if (mapping == NULL)
return (NS_LDAP_SUCCESS);
if (mapping[0] != NULL) {
mapped_attr = strdup(mapping[0]);
__s_api_free2dArray(mapping);
if (mapped_attr == NULL) {
return (NS_LDAP_MEMORY);
}
} else {
__s_api_free2dArray(mapping);
(void) snprintf(errstr, (2 * MAXERROR),
gettext("Attribute nisMapName is mapped to an "
"empty string.\n"));
MKERROR(LOG_ERR, *errp, NS_CONFIG_SYNTAX,
strdup(errstr), NS_LDAP_MEMORY);
return (NS_LDAP_CONFIG);
}
rc = __s_api_replace_mapped_attr_in_dn(
(const char *) automountmapname, (const char *) mapped_attr,
(const char *) *dn, &buffer);
free(mapped_attr);
if (buffer != NULL) {
free(*dn);
*dn = buffer;
}
return (rc);
}
int
__s_api_replace_mapped_attr_in_dn(const char *orig_attr,
const char *mapped_attr, const char *dn, char **new_dn)
{
char **dnArray = NULL;
char *cur = NULL, *start = NULL;
int i = 0;
boolean_t found = B_FALSE;
int len = 0, orig_len = 0, mapped_len = 0;
int dn_len = 0, tmp_len = 0;
*new_dn = NULL;
dnArray = ldap_explode_dn(dn, 0);
for (i = 0; dnArray[i] != NULL; i++) {
cur = strchr(dnArray[i], '=');
*cur = '\0';
if (strcasecmp(mapped_attr, dnArray[i]) == 0)
found = B_TRUE;
*cur = '=';
if (found)
break;
}
if (!found) {
__s_api_free2dArray(dnArray);
*new_dn = NULL;
return (NS_LDAP_SUCCESS);
}
mapped_len = strlen(mapped_attr);
orig_len = strlen(orig_attr);
dn_len = strlen(dn);
len = dn_len + orig_len - mapped_len + 1;
*new_dn = (char *)calloc(1, len);
if (*new_dn == NULL) {
__s_api_free2dArray(dnArray);
return (NS_LDAP_MEMORY);
}
cur = strstr(dn, dnArray[i]);
__s_api_free2dArray(dnArray);
start = *new_dn;
tmp_len = cur - dn;
(void) memcpy(start, dn, tmp_len);
start = start + (cur - dn);
(void) memcpy(start, orig_attr, orig_len);
cur = cur + mapped_len;
start = start + orig_len;
(void) strcpy(start, cur);
return (NS_LDAP_SUCCESS);
}
static int adj_filter_list(char *str);
static int adj_simple_filter(char *str);
static int unescape_filterval(char *val);
static int hexchar2int(char c);
static int adj_substring_filter(char *val);
static char *
resync_str(char *str, char *next, char c)
{
char *ret;
ret = str + strlen(str);
*next = c;
if (ret == next)
return (ret);
(void) strcat(str, next);
return (ret);
}
static char *
find_right_paren(char *s)
{
int balance;
boolean_t escape;
balance = 1;
escape = B_FALSE;
while (*s && balance) {
if (escape == B_FALSE) {
if (*s == '(')
balance++;
else if (*s == ')')
balance--;
}
if (*s == '\\' && !escape)
escape = B_TRUE;
else
escape = B_FALSE;
if (balance)
s++;
}
return (*s ? s : NULL);
}
static char *
adj_complex_filter(char *str)
{
char *next;
str++;
if ((next = find_right_paren(str)) == NULL)
return (NULL);
*next = '\0';
if (adj_filter_list(str) == -1)
return (NULL);
next = resync_str(str, next, ')');
next++;
return (next);
}
static int
adj_filter(char *str)
{
char *next;
int parens, balance;
boolean_t escape;
char *np, *cp, *dp;
parens = 0;
while (*str) {
switch (*str) {
case '(':
str++;
parens++;
switch (*str) {
case '&':
if ((str = adj_complex_filter(str)) == NULL)
return (-1);
parens--;
break;
case '|':
if ((str = adj_complex_filter(str)) == NULL)
return (-1);
parens--;
break;
case '!':
if ((str = adj_complex_filter(str)) == NULL)
return (-1);
parens--;
break;
case '(':
np = find_right_paren(str+1);
if (np == NULL)
return (-1);
for (dp = str, cp = str+1; cp < np; ) {
*dp++ = *cp++;
}
cp++;
while (*cp)
*dp++ = *cp++;
*dp = '\0';
parens--;
str--;
break;
default:
balance = 1;
escape = B_FALSE;
next = str;
while (*next && balance) {
if (escape == B_FALSE) {
if (*next == '(')
balance++;
else if (*next == ')')
balance--;
}
if (*next == '\\' && !escape)
escape = B_TRUE;
else
escape = B_FALSE;
if (balance)
next++;
}
if (balance != 0)
return (-1);
*next = '\0';
if (adj_simple_filter(str) == -1) {
return (-1);
}
next = resync_str(str, next, ')');
next++;
str = next;
parens--;
break;
}
break;
case ')':
str++;
parens--;
break;
case ' ':
str++;
break;
default:
next = strchr(str, '\0');
if (adj_simple_filter(str) == -1) {
return (-1);
}
str = next;
break;
}
}
return (parens ? -1 : 0);
}
static int
adj_filter_list(char *str)
{
char *next;
char save;
while (*str) {
while (*str && isspace(*str))
str++;
if (*str == '\0')
break;
if ((next = find_right_paren(str + 1)) == NULL)
return (-1);
save = *++next;
*next = '\0';
if (adj_filter(str) == -1)
return (-1);
next = resync_str(str, next, save);
str = next;
}
return (0);
}
static int
is_valid_attr(char *a)
{
for (; *a; a++) {
if (!isascii(*a)) {
return (0);
} else if (!isalnum(*a)) {
switch (*a) {
case '-':
case '.':
case ';':
case ':':
case '_':
break;
default:
return (0);
}
}
}
return (1);
}
static char *
find_star(char *s)
{
for (; *s; ++s) {
switch (*s) {
case '*':
return (s);
case '\\':
++s;
if (hexchar2int(s[0]) >= 0 && hexchar2int(s[1]) >= 0)
++s;
default:
break;
}
}
return (NULL);
}
static int
adj_simple_filter(char *str)
{
char *s, *s2, *s3, filterop;
char *value;
int ftype = 0;
int rc;
rc = -1;
if ((str = strdup(str)) == NULL) {
return (rc);
}
if ((s = strchr(str, '=')) == NULL) {
goto free_and_return;
}
value = s + 1;
*s-- = '\0';
filterop = *s;
if (filterop == '<' || filterop == '>' || filterop == '~' ||
filterop == ':') {
*s = '\0';
}
if (!is_valid_attr(str)) {
goto free_and_return;
}
switch (filterop) {
case '<':
case '>':
case '~':
break;
case ':':
s2 = s3 = NULL;
if ((s2 = strrchr(str, ':')) == NULL) {
goto free_and_return;
}
if (strcasecmp(s2, ":dn") == 0) {
*s2 = '\0';
} else {
*s2 = '\0';
if ((s3 = strrchr(str, ':')) != NULL) {
if (strcasecmp(s3, ":dn") != 0) {
goto free_and_return;
}
*s3 = '\0';
}
}
if (unescape_filterval(value) < 0) {
goto free_and_return;
}
rc = 0;
goto free_and_return;
default:
if (find_star(value) == NULL) {
ftype = 0;
} else if (strcmp(value, "*") == 0) {
ftype = 1;
} else {
rc = adj_substring_filter(value);
goto free_and_return;
}
break;
}
if (ftype != 0) {
rc = 0;
} else if (unescape_filterval(value) >= 0) {
rc = 0;
}
if (rc != -1) {
rc = 0;
}
free_and_return:
free(str);
return (rc);
}
static int
unescape_filterval(char *val)
{
boolean_t escape, firstdigit;
char *s;
firstdigit = B_FALSE;
escape = B_FALSE;
for (s = val; *s; s++) {
if (escape) {
if (hexchar2int(*s) < 0) {
if (firstdigit) {
escape = B_FALSE;
} else {
return (-1);
}
}
if (firstdigit) {
firstdigit = B_FALSE;
} else {
escape = B_FALSE;
}
} else if (*s != '\\') {
escape = B_FALSE;
} else {
escape = B_TRUE;
firstdigit = B_TRUE;
}
}
return (1);
}
static int
hexchar2int(char c)
{
if (c >= '0' && c <= '9') {
return (c - '0');
}
if (c >= 'A' && c <= 'F') {
return (c - 'A' + 10);
}
if (c >= 'a' && c <= 'f') {
return (c - 'a' + 10);
}
return (-1);
}
static int
adj_substring_filter(char *val)
{
char *nextstar;
for (; val != NULL; val = nextstar) {
if ((nextstar = find_star(val)) != NULL) {
*nextstar++ = '\0';
}
if (*val != '\0') {
if (unescape_filterval(val) < 0) {
return (-1);
}
}
}
return (0);
}
static int
validate_filter(ns_ldap_cookie_t *cookie)
{
char *filter = cookie->filter;
int rc;
rc = adj_filter(filter);
if (rc != 0) {
return (NS_LDAP_OP_FAILED);
}
return (NS_LDAP_SUCCESS);
}
static int
setup_acctmgmt_params(ns_ldap_cookie_t *cookie)
{
LDAPControl *req, **requestctrls;
req = calloc(1, sizeof (LDAPControl));
if (req == NULL)
return (NS_LDAP_MEMORY);
req->ldctl_iscritical = 1;
req->ldctl_oid = strdup(NS_LDAP_ACCOUNT_USABLE_CONTROL);
if (req->ldctl_oid == NULL) {
free(req);
return (NS_LDAP_MEMORY);
}
requestctrls = (LDAPControl **)calloc(2, sizeof (LDAPControl *));
if (requestctrls == NULL) {
ldap_control_free(req);
return (NS_LDAP_MEMORY);
}
requestctrls[0] = req;
cookie->p_serverctrls = requestctrls;
return (NS_LDAP_SUCCESS);
}
static int
get_new_acct_more_info(BerElement *ber, AcctUsableResponse_t *acctResp)
{
int rc = NS_LDAP_SUCCESS;
char errstr[MAXERROR];
ber_tag_t rTag = LBER_DEFAULT;
ber_len_t rLen = 0;
ber_int_t rValue;
char *last;
int berRC = 0;
for (rTag = ber_first_element(ber, &rLen, &last);
rTag != LBER_END_OF_SEQORSET;
rTag = ber_next_element(ber, &rLen, last)) {
berRC = 0;
switch (rTag) {
case 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
berRC = ber_scanf(ber, "b", &rValue);
if (berRC != LBER_ERROR) {
(acctResp->AcctUsableResp).more_info.
inactive = (rValue != 0) ? 1 : 0;
}
break;
case 1 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
berRC = ber_scanf(ber, "b", &rValue);
if (berRC != LBER_ERROR) {
(acctResp->AcctUsableResp).more_info.reset
= (rValue != 0) ? 1 : 0;
}
break;
case 2 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
berRC = ber_scanf(ber, "b", &rValue);
if (berRC != LBER_ERROR) {
(acctResp->AcctUsableResp).more_info.expired
= (rValue != 0) ? 1 : 0;
}
break;
case 3 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
berRC = ber_scanf(ber, "i", &rValue);
if (berRC != LBER_ERROR) {
(acctResp->AcctUsableResp).more_info.rem_grace
= rValue;
}
break;
case 4 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
berRC = ber_scanf(ber, "i", &rValue);
if (berRC != LBER_ERROR) {
(acctResp->AcctUsableResp).more_info.
sec_b4_unlock = rValue;
}
break;
default :
(void) sprintf(errstr,
gettext("invalid reason tag 0x%x"), rTag);
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
if (berRC == LBER_ERROR) {
(void) sprintf(errstr,
gettext("error 0x%x decoding value for "
"tag 0x%x"), berRC, rTag);
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
}
if (rc != NS_LDAP_SUCCESS) {
break;
}
}
return (rc);
}
static int
get_old_acct_opt_more_info(ber_tag_t tag, BerElement *ber,
AcctUsableResponse_t *acctResp)
{
int rc = NS_LDAP_SUCCESS;
char errstr[MAXERROR];
ber_len_t len;
int rem_grace, sec_b4_unlock;
switch (tag) {
case 2:
if ((tag = ber_scanf(ber, "i", &rem_grace)) == LBER_ERROR) {
(void) sprintf(errstr, gettext("Can not get "
"rem_grace"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
(acctResp->AcctUsableResp).more_info.rem_grace = rem_grace;
if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
(void) sprintf(errstr, gettext("No more "
"optional data"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
break;
}
if (tag == 3) {
if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
(void) sprintf(errstr,
gettext("Can not get sec_b4_unlock "
"- 1st case"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
(acctResp->AcctUsableResp).more_info.sec_b4_unlock =
sec_b4_unlock;
} else {
(void) sprintf(errstr, gettext("Unknown tag "
"- 1st case"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
break;
case 3:
if (ber_scanf(ber, "i", &sec_b4_unlock) == LBER_ERROR) {
(void) sprintf(errstr, gettext("Can not get "
"sec_b4_unlock - 2nd case"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
(acctResp->AcctUsableResp).more_info.sec_b4_unlock =
sec_b4_unlock;
break;
default:
(void) sprintf(errstr, gettext("Unknown tag - 2nd case"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
return (rc);
}
#define DS52p4_USABLE 0x00
#define DS52p4_NOT_USABLE 0x01
#define NEW_USABLE 0x00 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE
#define NEW_NOT_USABLE 0x01 | LBER_CLASS_CONTEXT | LBER_CONSTRUCTED
static int
parse_acct_cont_resp_msg(LDAPControl **ectrls, AcctUsableResponse_t *acctResp)
{
int rc = NS_LDAP_SUCCESS;
BerElement *ber;
ber_tag_t tag;
ber_len_t len;
int i;
char errstr[MAXERROR];
int seconds_before_expiry;
int inactive, reset, expired;
if (ectrls == NULL) {
(void) sprintf(errstr, gettext("Invalid ectrls parameter"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
return (NS_LDAP_INVALID_PARAM);
}
for (i = 0; ectrls[i] != NULL; i++) {
if (strcmp(ectrls[i]->ldctl_oid, NS_LDAP_ACCOUNT_USABLE_CONTROL)
== 0) {
break;
}
}
if (ectrls[i] == NULL) {
(void) sprintf(errstr, gettext("Account Usable Control "
"not found"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
return (NS_LDAP_NOTFOUND);
}
if ((ber = ber_init(&ectrls[i]->ldctl_value)) == NULL)
return (NS_LDAP_MEMORY);
if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
(void) sprintf(errstr, gettext("Error decoding 1st tag"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
ber_free(ber, 1);
return (NS_LDAP_INTERNAL);
}
switch (tag) {
case DS52p4_USABLE:
case NEW_USABLE:
acctResp->choice = 0;
if (ber_scanf(ber, "i", &seconds_before_expiry)
== LBER_ERROR) {
(void) sprintf(errstr, gettext("Can not get "
"seconds_before_expiry"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
(acctResp->AcctUsableResp).seconds_before_expiry =
seconds_before_expiry;
break;
case DS52p4_NOT_USABLE:
acctResp->choice = 1;
if (ber_scanf(ber, "{bbb", &inactive, &reset, &expired)
== LBER_ERROR) {
(void) sprintf(errstr, gettext("Can not get "
"inactive/reset/expired"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
(acctResp->AcctUsableResp).more_info.inactive =
((inactive == 0) ? 0 : 1);
(acctResp->AcctUsableResp).more_info.reset =
((reset == 0) ? 0 : 1);
(acctResp->AcctUsableResp).more_info.expired =
((expired == 0) ? 0 : 1);
(acctResp->AcctUsableResp).more_info.rem_grace = 0;
(acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
if ((tag = ber_peek_tag(ber, &len)) == LBER_ERROR) {
(void) sprintf(errstr, gettext("No optional data"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
break;
}
rc = get_old_acct_opt_more_info(tag, ber, acctResp);
break;
case NEW_NOT_USABLE:
acctResp->choice = 1;
(acctResp->AcctUsableResp).more_info.inactive = 0;
(acctResp->AcctUsableResp).more_info.reset = 0;
(acctResp->AcctUsableResp).more_info.expired = 0;
(acctResp->AcctUsableResp).more_info.rem_grace = 0;
(acctResp->AcctUsableResp).more_info.sec_b4_unlock = 0;
if (len == 0) {
(void) sprintf(errstr, gettext("more_info is "
"empty, using default values"));
syslog(LOG_DEBUG, "libsldap: %s", errstr);
break;
}
rc = get_new_acct_more_info(ber, acctResp);
break;
default:
(void) sprintf(errstr, gettext("unknwon coding style "
"(tag: 0x%x)"), tag);
syslog(LOG_DEBUG, "libsldap: %s", errstr);
rc = NS_LDAP_INTERNAL;
break;
}
ber_free(ber, 1);
return (rc);
}
static int
getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp,
ns_conn_user_t *conn_user)
{
int scope, rc;
ns_ldap_cookie_t *cookie;
ns_ldap_search_desc_t **sdlist = NULL;
ns_ldap_search_desc_t *dptr;
ns_ldap_error_t *error = NULL;
char **dns = NULL;
char service[] = "shadow";
if (user == NULL || acctResp == NULL)
return (NS_LDAP_INVALID_PARAM);
cookie = init_search_state_machine();
if (cookie == NULL)
return (NS_LDAP_MEMORY);
cookie->conn_user = conn_user;
rc = __s_api_toFollowReferrals(0,
&cookie->followRef, &error);
if (rc != NS_LDAP_SUCCESS) {
(void) __ns_ldap_freeError(&error);
goto out;
}
rc = __s_api_get_SSD_from_SSDtoUse_service(service,
&sdlist, &error);
if (rc != NS_LDAP_SUCCESS) {
(void) __ns_ldap_freeError(&error);
goto out;
}
if (sdlist == NULL) {
sdlist = (ns_ldap_search_desc_t **)calloc(2,
sizeof (ns_ldap_search_desc_t *));
if (sdlist == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
dptr = (ns_ldap_search_desc_t *)
calloc(1, sizeof (ns_ldap_search_desc_t));
if (dptr == NULL) {
free(sdlist);
rc = NS_LDAP_MEMORY;
goto out;
}
sdlist[0] = dptr;
rc = __s_api_getDNs(&dns, service, &cookie->errorp);
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
__s_api_free2dArray(dns);
dns = NULL;
}
(void) __ns_ldap_freeError(&(cookie->errorp));
cookie->errorp = NULL;
goto out;
}
dptr->basedn = strdup(dns[0]);
if (dptr->basedn == NULL) {
free(sdlist);
free(dptr);
if (dns) {
__s_api_free2dArray(dns);
dns = NULL;
}
rc = NS_LDAP_MEMORY;
goto out;
}
__s_api_free2dArray(dns);
dns = NULL;
scope = 0;
rc = __s_api_getSearchScope(&scope, &cookie->errorp);
dptr->scope = scope;
}
cookie->sdlist = sdlist;
cookie->service = strdup(service);
if (cookie->service == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
(void) asprintf(&cookie->i_filter, "(uid=%s)", user);
if (cookie->i_filter == NULL) {
rc = NS_LDAP_MEMORY;
goto out;
}
if ((rc = setup_acctmgmt_params(cookie)) != NS_LDAP_SUCCESS)
goto out;
rc = search_state_machine(cookie, GET_ACCT_MGMT_INFO, 0);
rc = cookie->err_rc;
if (rc != NS_LDAP_SUCCESS)
(void) __ns_ldap_freeError(&(cookie->errorp));
if (cookie->result == NULL)
goto out;
if ((rc = parse_acct_cont_resp_msg(cookie->resultctrl, acctResp))
!= NS_LDAP_SUCCESS)
goto out;
rc = NS_LDAP_SUCCESS;
out:
delete_search_cookie(cookie);
return (rc);
}
int
__ns_ldap_getAcctMgmt(const char *user, AcctUsableResponse_t *acctResp)
{
ns_conn_user_t *cu = NULL;
int try_cnt = 0;
int rc = NS_LDAP_SUCCESS;
ns_ldap_error_t *error = NULL;
for (;;) {
if (__s_api_setup_retry_search(&cu, NS_CONN_USER_SEARCH,
&try_cnt, &rc, &error) == 0)
break;
rc = getAcctMgmt(user, acctResp, cu);
}
return (rc);
}