ns_reads.c revision 8142c2b2a11acff39ec7e0576c566a751eb30ba6
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stdlib.h>
#include <libintl.h>
#include <ctype.h>
#include <syslog.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include "ns_sldap.h"
#include "ns_internal.h"
#include "ns_cache_door.h"
#define _NIS_FILTER "nisdomain=*"
#define _NIS_DOMAIN "nisdomain"
static const char *nis_domain_attrs[] = {
(char *)NULL
};
void
{
int j, k = 0;
return;
return;
}
for (j = 0; j < ep->attr_count; j++) {
continue;
}
}
}
}
static void
{
LDAPControl **ctrl;
return;
}
/*
* Convert attribute type in a RDN that has an attribute mapping to the
* original mappped type.
* e.g.
* cn<->cn-st and iphostnumber<->iphostnumber-st
* cn-st=aaa+iphostnumber-st=10.10.01.01
* is mapped to
* cn=aaa+iphostnumber=10.10.01.01
*
* Input - service: e.g. hosts, passwd etc.
* rdn: RDN
* Return: NULL - No attribute mapping in the RDN
* Non-NULL - The attribute type(s) in the RDN are mapped and
* the memory is allocated for the new rdn.
*
*/
static char *
/* Break down "type=value\0" pairs. Assume RDN is normalized */
return (NULL);
return (NULL);
}
attr_mapped = 0;
for (i = 0; i < nAttr; i++) {
/* Parse type=value pair */
goto cleanup;
/* Reverse map: e.g. cn-sm -> cn */
/* The attribute mapping is found */
attr_mapped = 1;
/* "type=value\0" */
/* Reconstruct type=value pair. A string is allocated */
goto cleanup;
}
mapped_attrs[i] = attr;
} else {
/*
* No attribute mapping. attrs[i] is going to be copied
* later. Restore "type\0value\0" back to
* "type=value\0".
*/
}
}
if (attr_mapped == 0)
/* No attribute mapping. Don't bother to reconstruct RDN */
goto cleanup;
len = 0;
/* Reconstruct RDN from type=value pairs */
for (i = 0; i < nAttr; i++) {
if (mapped_attrs[i])
else
/* Add 1 for "+" */
len++;
}
goto cleanup;
for (i = 0; i < nAttr; i++) {
if (i > 0)
/* Add seperator */
if (mapped_attrs[i])
else
}
if (mapped_attrs) {
if (attr_mapped) {
for (i = 0; i < nAttr; i++) {
if (mapped_attrs[i])
free(mapped_attrs[i]);
}
}
}
return (new_rdn);
}
/*
* Convert attribute type in a DN that has an attribute mapping to the
* original mappped type.
* e.g
* The mappings are cn<->cn-sm, iphostnumber<->iphostnumber-sm
*
* dn: cn-sm=aaa+iphostnumber-sm=9.9.9.9,dc=central,dc=sun,dc=com
* is converted to
* dn: cn=aaa+iphostnumber=9.9.9.9,dc=central,dc=sun,dc=com
*
* Input - service: e.g. hosts, passwd etc.
* dn: the value of a distinguished name
* Return - NULL: error
* non-NULL: A converted DN and the memory is allocated
*/
static char *
char **mapped_rdns;
return (NULL);
return (NULL);
return (NULL);
}
rdn_mapped = 0;
/* Break down RDNs in a DN */
for (i = 0; i < nRdn; i++) {
mapped_rdns[i] = new_rdn;
rdn_mapped = 1;
}
}
if (rdn_mapped == 0) {
/*
* No RDN contains any attribute mapping.
* Don't bother to reconstruct DN from RDN. Copy DN directly.
*/
goto cleanup;
}
/*
* Reconstruct dn from RDNs.
* Calculate the length first.
*/
for (i = 0; i < nRdn; i++) {
if (mapped_rdns[i])
else
/* add 1 for ',' */
len ++;
}
goto cleanup;
for (i = 0; i < nRdn; i++) {
if (i > 0)
/* Add seperator */
if (mapped_rdns[i])
else
}
if (mapped_rdns) {
if (rdn_mapped) {
for (i = 0; i < nRdn; i++) {
if (mapped_rdns[i])
free(mapped_rdns[i]);
}
}
}
return (new_dn);
}
/*
* Convert a single ldap entry from a LDAPMessage
* into an ns_ldap_entry structure.
* Schema map the entry if specified in flags
*/
static int
const char *service,
LDAPMessage *e,
int flags,
{
char **mapping;
char *dn;
int nAttrs = 0;
int i, j, k = 0;
char **gecos_mapping = NULL;
int schema_mapping_existed = FALSE;
int gecos_mapping_existed = FALSE;
int gecos_attr_matched;
int auto_service = FALSE;
int rc = NS_LDAP_SUCCESS;
return (NS_LDAP_INVALID_PARAM);
return (NS_LDAP_MEMORY);
auto_service = TRUE;
/*
* see if schema mapping existed for the given service
*/
if (mapping) {
} else if (auto_service) {
/*
* If service == auto_* and no
* schema mapping found
* then try automount
* There is certain case that schema mapping exist
* but __ns_ldap_getOrigAttribute(service,
* NS_HASH_SCHEMA_MAPPING_EXISTED);
* returns NULL.
* e.g.
* NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
* NS_LDAP_OBJECTCLASSMAP = automount:automountMap=MynisMap
* NS_LDAP_OBJECTCLASSMAP = automount:automount=MynisObject
*
* Make a check for schema_mapping_existed here
* so later on __s_api_convert_automountmapname won't be called
* unnecessarily. It is also used for attribute mapping
* and objectclass mapping.
*/
if (mapping) {
}
}
nAttrs++;
}
/*
* add 1 for "gecos" 1 to N attribute mapping,
* just in case it is needed.
* ep->attr_count will be updated later if that is true.
*/
sizeof (ns_ldap_attr_t *));
return (NS_LDAP_MEMORY);
}
/* DN attribute */
return (NS_LDAP_MEMORY);
}
return (NS_LDAP_INVALID_PARAM);
}
return (NS_LDAP_MEMORY);
}
else
return (NS_LDAP_MEMORY);
}
error);
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
}
/* other attributes */
/* allocate new attr name */
if ((ap[j] = (ns_ldap_attr_t *)
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
else
/*
* if service == auto_* and no schema mapping found
* and schema_mapping_existed is TRUE and NS_LDAP_NOMAP
* is not set then try automount e.g.
* NS_LDAP_ATTRIBUTEMAP = automount:automountMapName=AAA
*/
attr);
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
} else {
/*
* for "gecos" 1 to N mapping,
* do not remove the mapped attribute,
* just create a new gecos attribute
* and append it to the end of the attribute list
*/
} else
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
/*
* 1 to N attribute mapping processing
* is only done for "gecos"
*/
/*
* get attribute mapping for "gecos",
* need to know the number and order of the
* mapped attributes
*/
if (gecos_mapping == NULL) {
if (gecos_mapping == NULL ||
gecos_mapping[0] == NULL) {
/*
* this should never happens,
* syslog the error
*/
"Attribute mapping "
"inconsistency "
"found for attributes "
"'%s' and '%s'."),
errstr);
if (gecos_mapping)
return (NS_LDAP_INTERNAL);
}
}
/*
* is this attribute the 1st, 2nd, or
* 3rd attr in the mapping list?
*/
for (i = 0; i < 3 && gecos_mapping[i]; i++) {
if (gecos_mapping[i] &&
attr) == 0) {
gecos_val_index[i] = j;
break;
}
}
if (gecos_attr_matched == FALSE) {
/*
* Not match found.
* This should never happens,
* syslog the error
*/
"Attribute mapping "
"inconsistency "
"found for attributes "
"'%s' and '%s'."),
return (NS_LDAP_INTERNAL);
}
}
}
if ((ap[j]->value_count =
ldap_count_values(vals)) == 0) {
continue;
} else {
sizeof (char *));
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
}
/* map object classes if necessary */
if ((flags & NS_LDAP_NOMAP) == 0 &&
for (k = 0; k < ap[j]->value_count; k++) {
mapping =
/*
* if service == auto_* and no
* schema mapping found
* then try automount
*/
mapping =
"automount", vals[k]);
} else {
}
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
}
} else {
for (k = 0; k < ap[j]->value_count; k++) {
if (gecos_mapping)
return (NS_LDAP_MEMORY);
}
}
}
}
}
if (gecos_mapping) {
}
/* special processing for gecos 1 to up to 3 attribute mapping */
if (schema_mapping_existed && gecos_mapping_existed) {
int f = -1;
for (i = 0; i < 3; i++) {
k = gecos_val_index[i];
/*
* f is the index of the first returned
* attribute which "gecos" attribute mapped to
*/
if (k != -1 && f == -1)
f = k;
if (k == f) {
/*
* Create and fill in the last reserved
* ap with the data from the "gecos"
* mapping attributes
*/
calloc(1,
sizeof (ns_ldap_attr_t));
return (NS_LDAP_MEMORY);
}
2, sizeof (char *));
return (NS_LDAP_MEMORY);
}
/* add 1 more for a possible "," */
(char *)calloc(
2, 1);
return (NS_LDAP_MEMORY);
}
return (NS_LDAP_MEMORY);
}
} else {
/*
* realloc to add "," and
* ap[k]->attrvalue[0]
*/
attrvalue[0]) +
attrvalue[0]) + 2);
return (NS_LDAP_MEMORY);
}
",");
}
}
}
}
return (NS_LDAP_SUCCESS);
}
static int
{
int ret;
#ifdef DEBUG
#endif
return (NS_LDAP_INVALID_PARAM);
}
if (ret != NS_LDAP_SUCCESS) {
return (ret);
}
return (NS_LDAP_MEMORY);
}
} else {
}
return (NS_LDAP_SUCCESS);
}
static int
__s_api_get_cachemgr_data(const char *type,
{
union {
char s_b[DOORBUFFERSIZE];
} space;
int ndata;
int adata;
int rc;
#ifdef DEBUG
#endif
return (-1);
"%s%s%s",
type,
from);
adata = sizeof (ldap_call_t) +
return (-1);
else
return (NS_LDAP_SUCCESS);
}
static int
__s_api_set_cachemgr_data(const char *type,
{
union {
char s_b[DOORBUFFERSIZE];
} space;
int ndata;
int adata;
int rc;
#ifdef DEBUG
#endif
return (-1);
"%s%s%s%s%s",
type,
from,
to);
adata = sizeof (ldap_call_t) +
return (-1);
return (NS_LDAP_SUCCESS);
}
static char *
__s_api_remove_rdn_space(char *rdn)
{
/* if no space(s) to remove, return */
return (rdn);
/* if no '=' separator, return */
return (rdn);
/* now two strings, type and value */
*eqsign = '\0';
/* remove type's leading spaces */
tf++;
/* remove type's trailing spaces */
tl--;
/* add '=' separator back */
*(++tl) = '=';
/* remove value's leading spaces */
vf++;
/* remove value's trailing spaces */
*vl-- = '\0';
/* move value up if necessary */
return (tf);
}
static
{
return (NULL);
/* assign other state variables */
} else {
}
return (cookie);
}
static void
{
return;
if (cookie->ctrlCookie)
if (cookie->resultctrl)
}
static int
{
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;
char *c, *last_copied;
char *filter_c, *filter_c_next;
int at_least_one = FALSE;
char **mapping;
int auto_service = FALSE;
return (NS_LDAP_INVALID_PARAM);
*new_filter = NULL;
/*
* count the number of '=' char
*/
for (c = filter; *c; c++) {
if (*c == TOKENSEPARATOR)
num_eq++;
}
auto_service = TRUE;
/*
* See if schema mapping existed for the given service.
* If not, just return success.
*/
/*
* if service == auto_* and no
* schema mapping found
* then try automount
*/
"automount", NS_HASH_SCHEMA_MAPPING_EXISTED);
if (mapping)
else
return (NS_LDAP_SUCCESS);
/*
* no '=' sign, just say OK and return nothing
*/
if (num_eq == 0)
return (NS_LDAP_SUCCESS);
/*
* Make a copy of the filter string
* for saving the name of the objectclasses or
* attributes that need to be passed to the
* objectclass or attribute mapping functions.
* pointer "info->from_name" points to the locations
* within this string.
*
* The input filter string, filter, will be used
* to indicate where these names start and end.
* pointers "info->name_start" and "info->name_end"
* point to locations within the input filter string,
* and are used at the end of this function to
* merge the original filter data with the
* mapped objectclass or attribute names.
*/
return (NS_LDAP_MEMORY);
/*
* get memory for info arrays
*/
sizeof (filter_mapping_info_t *));
return (NS_LDAP_MEMORY);
}
/*
* find valid '=' for further processing,
* ignore the "escaped =" (.i.e. "\="), or
* "=" in quoted string
*/
for (c = filter_c; *c; c++) {
switch (*c) {
case TOKENSEPARATOR:
sizeof (filter_mapping_info_t));
if (!info1) {
for (i = 0; i < num_veq; i++)
return (NS_LDAP_MEMORY);
}
/*
* remember the location of this "="
*/
/*
* skip until the end of the attribute value
*/
}
break;
case CPARATOK:
/*
* mark the end of the attribute value
*/
if (!in_quote)
break;
case QUOTETOK:
/*
*/
break;
case '\\':
/*
* ignore escape characters
* don't skip if next char is '\0'
*/
if (!in_quote)
if (*(++c) == '\0')
c--;
break;
}
}
/*
* for each valid "=" found, get the name to
* be mapped
*/
for (i = 0; i < num_veq; i++) {
/*
* look at the left side of "=" to see
* if assertion is "objectclass=<ocname>"
* or "<attribute name>=<attribute value>"
*
* first skip spaces before "=".
* Note that filter_c_next may not point to the
* start of the filter string. For i > 0,
* it points to the end of the last name processed + 2
*/
;
/*
* mark the end of the left side string (the key)
*/
*tail = '\0';
/*
* find the start of the key
*/
key = filter_c_next;
for (c = tail; filter_c_next <= c; c--) {
/* OPARATOK is '(' */
if (*c == OPARATOK ||
*c == SPACETOK) {
key = c + 1;
break;
}
}
oc_len) == 0) {
/*
* assertion is "objectclass=ocname",
* ocname is the one needs to be mapped
*
* skip spaces after "=" to find start
* of the ocname
*/
;
/* ignore empty ocname */
if (!(*head))
continue;
/*
* now find the end of the ocname
*/
for (c = head; ; c++) {
/* CPARATOK is ')' */
if (*c == CPARATOK ||
*c == '\0' ||
*c == SPACETOK) {
*c = '\0';
c - filter_c - 1 +
filter_c_next = c + 1;
break;
}
}
}
}
/*
* assertion is not "objectclass=ocname",
* assume assertion is "<key> = <value>",
* <key> is the one needs to be mapped
*/
}
}
/* perform schema mapping */
for (i = 0; i < num_veq; i++) {
continue;
else
/*
* If no mapped attribute/objectclass is found
* and service == auto*
* try to find automount's
* mapped attribute/objectclass
*/
__ns_ldap_getMappedAttributes("automount",
else
__ns_ldap_getMappedObjectClass("automount",
}
at_least_one = TRUE;
} else {
/*
* multiple mapping
* not allowed
*/
"Multiple attribute or objectclass "
"mapping for '%s' in filter "
"'%s' not allowed."),
if (err)
for (j = 0; j < num_veq; j++) {
}
return (NS_LDAP_CONFIG);
}
}
if (at_least_one) {
for (i = 0; i < num_veq; i++) {
}
if (*new_filter == NULL) {
for (j = 0; j < num_veq; j++) {
}
return (NS_LDAP_MEMORY);
}
for (i = 0; i < num_veq; i++) {
/*
* copy the original filter data
* between the last name and current
* name
*/
(void) strncat(*new_filter,
last_copied + 1,
info[i]->name_start -
last_copied - 1);
/* the data is copied */
/*
* replace the name with
* the mapped name
*/
}
/* copy the filter data after the last name */
if (i == (num_veq -1) &&
last_copied - 1);
}
}
/* free memory */
for (j = 0; j < num_veq; j++) {
}
return (NS_LDAP_SUCCESS);
}
static int
{
int scope;
int baselen;
int rc;
void **param;
if (scope)
else
case NS_LDAP_SCOPE_BASE:
break;
case NS_LDAP_SCOPE_ONELEVEL:
break;
case NS_LDAP_SCOPE_SUBTREE:
break;
}
}
return (-1);
} else {
return (-1);
}
}
} else {
return (-1);
}
}
/*
* perform attribute/objectclass mapping on filter
*/
if (rc != NS_LDAP_SUCCESS) {
return (-1);
} else {
/*
* get_mapped_filter returns
* NULL filter pointer, if
* no mapping was done
*/
if (filter) {
}
}
}
/*
* validate filter to make sure it's legal
* [remove redundant ()'s]
*/
if (rc != NS_LDAP_SUCCESS) {
return (-1);
}
if (rc != NS_LDAP_SUCCESS) {
return (-1);
}
return (-1);
}
(void) __ns_ldap_freeParam(¶m);
} else {
}
return (0);
}
static int
{
}
}
return (-1);
}
return (0);
}
static int
{
int rc;
int fail_if_new_pwd_reqd = 1;
/*
* If password control attached in *cookie->errorp,
* e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
* free the error structure (we do not need
* the sec_to_expired info).
* Reset rc to NS_LDAP_SUCCESS.
*/
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
}
if (rc != NS_LDAP_SUCCESS) {
return (-1);
}
return (0);
}
static int
{
int rc;
int fail_if_new_pwd_reqd = 1;
}
/*
* If password control attached in *cookie->errorp,
* e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
* free the error structure (we do not need
* the sec_to_expired info).
* Reset rc to NS_LDAP_SUCCESS.
*/
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
}
if (rc != NS_LDAP_SUCCESS) {
return (-1);
}
return (0);
}
static int
{
int rc;
int fail_if_new_pwd_reqd = 1;
}
/*
* If password control attached in *cookie->errorp,
* e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
* free the error structure (we do not need
* the sec_to_expired info).
* Reset rc to NS_LDAP_SUCCESS.
*/
if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
(void) __ns_ldap_freeError(
}
if (rc != NS_LDAP_SUCCESS) {
return (-1);
}
return (0);
}
static int
{
int rc;
if (rc == NS_LDAP_SUCCESS) {
return (1);
}
if (rc == NS_LDAP_SUCCESS) {
return (1);
}
return (0);
}
static int
{
LDAPControl **ctrls;
int rc;
if (rc != LDAP_SUCCESS) {
return (rc);
}
if (rc != LDAP_SUCCESS) {
return (rc);
}
vlist.ldvlist_size = 0;
if (rc != LDAP_SUCCESS) {
&rc);
return (rc);
}
return (LDAP_NO_MEMORY);
}
return (LDAP_SUCCESS);
}
static int
{
LDAPControl **ctrls;
int rc;
if (rc != LDAP_SUCCESS) {
&rc);
return (rc);
}
return (LDAP_NO_MEMORY);
}
return (LDAP_SUCCESS);
}
static void
{
/*
* Only follow one level of referrals, i.e.
* if already in referral mode, do nothing
*/
NULL, 0);
if (rc != NS_LDAP_SUCCESS) {
return;
}
if (errCode == LDAP_REFERRAL) {
i++) {
/* add to referral list */
referrals[i],
if (rc != NS_LDAP_SUCCESS) {
break;
}
}
}
}
}
static void
{
int i, rc;
/*
* Only follow one level of referrals, i.e.
* if already in referral mode, do nothing
*/
return;
}
/* add to referral list */
refurls[i],
if (rc != NS_LDAP_SUCCESS) {
break;
}
}
/* free allocated storage */
}
}
static ns_state_t
{
char *err;
int i, rc;
int errCode;
int finished = 0;
unsigned long target_posp = 0;
unsigned long list_size = 0;
unsigned int count = 0;
if (rc != LDAP_SUCCESS) {
gettext("LDAP ERROR (%d): %s.\n"),
NULL);
return (LDAP_ERROR);
}
if (errCode == LDAP_REFERRAL) {
i++) {
/* add to referral list */
referrals[i],
if (rc != NS_LDAP_SUCCESS) {
if (retCtrls)
retCtrls);
return (ERROR);
}
}
if (retCtrls)
return (END_RESULT);
}
if (retCtrls) {
if (rc == LDAP_SUCCESS) {
finished = 1;
}
}
}
else
finished = 1;
if (rc != LDAP_SUCCESS) {
gettext("LDAP ERROR (%d): %s.\n"),
NULL);
return (LDAP_ERROR);
}
if (errCode == LDAP_REFERRAL) {
i++) {
/* add to referral list */
referrals[i],
if (rc != NS_LDAP_SUCCESS) {
if (retCtrls)
retCtrls);
return (ERROR);
}
}
if (retCtrls)
return (END_RESULT);
}
if (retCtrls) {
if (cookie->ctrlCookie)
if (rc == LDAP_SUCCESS) {
finished = 1;
}
}
else
finished = 1;
}
return (NEXT_VLV);
return (NEXT_PAGE);
if (finished)
return (END_RESULT);
return (ERROR);
}
/*
* This state machine performs one or more LDAP searches to a given
* directory server using service search descriptors and schema
* mapping as appropriate. The approximate pseudocode for
* this routine is the following:
* and the current service search descriptor list
* or default search filter parameters
* foreach (service search filter) {
* initialize the filter [via filter_init if appropriate]
* get a valid session/connection (preferably the current one)
* Recover if the connection is lost
* perform the search
* foreach (result entry) {
* process result [via callback if appropriate]
* save result for caller if accepted.
* exit and return all collected if allResults found;
* }
* }
* return collected results and exit
*/
static
{
char *err;
errstr[0] = '\0';
for (;;) {
case CLEAR_RESULTS:
}
break;
case GET_ACCT_MGMT_INFO:
/*
* Set the flag to get ldap account management controls.
*/
break;
case EXIT:
/* state engine/connection cleaned up in delete */
}
}
return (EXIT);
case INIT:
}
}
break;
case NEXT_SEARCH_DESCRIPTOR:
/* get next search descriptor */
} else {
}
break;
case GET_SESSION:
if (get_current_session(cookie) < 0)
else
break;
case NEXT_SESSION:
if (get_next_session(cookie) < 0)
else
break;
case RESTART_SESSION:
break;
}
gettext("Session error no available conn.\n"),
state);
NULL);
break;
case NEXT_SEARCH:
/* setup referrals search if necessary */
if (setup_referral_search(cookie) < 0) {
break;
}
} else if (setup_next_search(cookie) < 0) {
break;
}
if (paging_supported(cookie)) {
if (cookie->use_paging &&
else
break;
}
}
break;
case NEXT_VLV:
if (rc != LDAP_SUCCESS) {
break;
}
break;
case NEXT_PAGE:
if (rc != LDAP_SUCCESS) {
break;
}
break;
case ONE_SEARCH:
break;
case DO_SEARCH:
0,
NULL,
&cookie->search_timeout, 0,
if (rc != LDAP_SUCCESS) {
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM ||
rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) {
/*
* If not able to reach the
* server, inform the ldap
* cache manager that the
* server should be removed
* from it's server list.
* Thus, the manager will not
* return this server on the next
* get-server request and will
* also reduce the server list
* refresh TTL, so that it will
* find out sooner when the server
* is up again.
*/
if (rc == LDAP_CONNECT_ERROR ||
rc == LDAP_SERVER_DOWN) {
== NS_LDAP_AUTH_NONE) {
/*
* Couldn't remove
* server from server
* list.
* Exit to avoid
* potential infinite
* loop.
*/
}
/*
* NS_LDAP_NEW_CONN
* indicates that the
* connection should
* be deleted, not
* kept alive
*/
cookie->
-1;
}
}
break;
}
break;
}
break;
case NEXT_RESULT:
if (rc == LDAP_RES_SEARCH_RESULT) {
/* check and process referrals info */
cookie);
break;
}
/* handle referrals if necessary */
if (rc == LDAP_RES_SEARCH_REFERENCE) {
break;
}
if (rc != LDAP_RES_SEARCH_ENTRY) {
switch (rc) {
case 0:
rc = LDAP_TIMEOUT;
break;
case -1:
break;
default:
break;
}
if (rc == LDAP_TIMEOUT ||
rc == LDAP_SERVER_DOWN) {
if (rc == LDAP_TIMEOUT)
(void) __s_api_removeServer(
}
}
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM) {
break;
}
break;
}
/* else LDAP_RES_SEARCH_ENTRY */
/* get account management response control */
&(cookie->resultctrl));
if (rc != LDAP_SUCCESS) {
break;
}
}
if (rc != NS_LDAP_SUCCESS) {
break;
}
break;
case MULTI_RESULT:
if (rc == LDAP_RES_SEARCH_RESULT) {
if (rc != LDAP_SUCCESS) {
break;
}
break;
}
/* handle referrals if necessary */
if (rc == LDAP_RES_SEARCH_REFERENCE &&
break;
}
if (rc != LDAP_RES_SEARCH_ENTRY) {
switch (rc) {
case 0:
rc = LDAP_TIMEOUT;
break;
case -1:
break;
default:
break;
}
if (rc == LDAP_TIMEOUT ||
rc == LDAP_SERVER_DOWN) {
if (rc == LDAP_TIMEOUT)
(void) __s_api_removeServer(
}
}
rc == LDAP_UNAVAILABLE ||
rc == LDAP_UNWILLING_TO_PERFORM) {
break;
}
break;
}
/* else LDAP_RES_SEARCH_ENTRY */
if (rc != NS_LDAP_SUCCESS) {
break;
}
break;
case PROCESS_RESULT:
/* NOTE THIS STATE MAY BE PROCESSED BY CALLER */
rc = 0;
if (rc == NS_LDAP_CB_DONE) {
/* cb doesn't want any more data */
break;
} else if (rc != NS_LDAP_CB_NEXT) {
/* invalid return code */
break;
}
}
}
if (rc != 0) {
break;
}
/* NOTE PREVIOUS STATE SPECIFIES NEXT STATE */
break;
case END_PROCESS_RESULT:
break;
case END_RESULT:
/*
* XXX DO WE NEED THIS CASE?
* if (search is complete) {
* cookie->new_state = EXIT;
* } else
*/
/*
* entering referral mode if necessary
*/
else
break;
case NEXT_REFERRAL:
/* get next referral info */
else
/* check see if done with all referrals */
else {
}
break;
case GET_REFERRAL_SESSION:
if (get_referral_session(cookie) < 0)
else {
}
break;
case LDAP_ERROR:
if (cookie->err_from_result) {
gettext("LDAP ERROR (%d): "
"Error occurred during"
" receiving results. "
"This may be due to a "
"stalled connection."),
gettext("LDAP ERROR (%d): "
"Error occurred during"
" receiving results. %s"
}
} else
gettext("LDAP ERROR (%d): %s."),
if (cookie->err_from_result) {
} else {
}
return (ERROR);
default:
case ERROR:
gettext("Internal State machine exit (%d).\n"),
NULL);
return (ERROR);
}
}
}
/*NOTREACHED*/
#if 0
gettext("Unexpected State machine error.\n"));
return (ERROR);
#endif
}
/*
* __ns_ldap_list performs one or more LDAP searches to a given
* directory server using service search descriptors and schema
* mapping as appropriate.
*/
int
const char *service,
const char *filter,
char **realfilter, const void *userdata),
const char * const *attribute,
const int flags,
const void *userdata)
{
int scope;
int rc;
int from_result;
/* Initialize State machine cookie */
return (NS_LDAP_MEMORY);
}
/* see if need to follow referrals */
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
/* get the service descriptor - or create a default one */
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
/* Create default service Desc */
sizeof (ns_ldap_search_desc_t *));
return (NS_LDAP_MEMORY);
}
dptr = (ns_ldap_search_desc_t *)
return (NS_LDAP_MEMORY);
}
/* default base */
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
}
return (rc);
}
/* default scope */
scope = 0;
}
/*
*/
if (flags & NS_LDAP_PAGE_CTRL)
else
/* Set up other arguments */
if (init_filter_cb != NULL) {
}
}
if (service) {
return (NS_LDAP_MEMORY);
}
}
/* Process search */
/* Copy results back to user */
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
/*
* __s_api_find_domainname performs one or more LDAP searches to
* find the value of the nisdomain attribute associated with
* the input DN
*/
static int
const char *dn,
char **domainname,
{
int rc;
char **value;
int flags = 0;
*domainname = NULL;
/* Initialize State machine cookie */
return (NS_LDAP_MEMORY);
}
/* see if need to follow referrals */
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
/* Create default service Desc */
sizeof (ns_ldap_search_desc_t *));
return (NS_LDAP_MEMORY);
}
dptr = (ns_ldap_search_desc_t *)
return (NS_LDAP_MEMORY);
}
/* search base is dn */
/* search scope is base */
/* search filter is "nisdomain=*" */
/* Process search */
/* Copy domain name if found */
if (rc != NS_LDAP_SUCCESS)
if (rc == NS_LDAP_SUCCESS) {
if (value[0])
else
}
return (rc);
}
int
const char *service,
const char *filter,
char **realfilter, const void *userdata),
const char * const *attribute,
const int flags,
void **vcookie,
const void *userdata)
{
int scope;
int rc;
/* get the service descriptor - or create a default one */
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
/* Create default service Desc */
sizeof (ns_ldap_search_desc_t *));
return (NS_LDAP_MEMORY);
}
dptr = (ns_ldap_search_desc_t *)
return (NS_LDAP_MEMORY);
}
/* default base */
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
}
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(
&sdlist);
}
return (rc);
}
/* default scope */
scope = 0;
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(&sdlist);
}
return (NS_LDAP_MEMORY);
}
}
/* Initialize State machine cookie */
if (sdlist) {
(void) __ns_ldap_freeSearchDescriptors(&sdlist);
}
return (NS_LDAP_MEMORY);
}
/* see if need to follow referrals */
if (rc != NS_LDAP_SUCCESS) {
return (rc);
}
/*
*/
if (flags & NS_LDAP_NO_PAGE_CTRL)
else
/* Set up other arguments */
if (init_filter_cb != NULL) {
}
cookie->use_usercb = 0;
if (service) {
return (NS_LDAP_MEMORY);
}
}
for (;;) {
switch (state) {
case PROCESS_RESULT:
return (NS_LDAP_SUCCESS);
case LDAP_ERROR:
ONE_STEP);
/* FALLTHROUGH */
case ERROR:
return (rc);
case EXIT:
if (rc != NS_LDAP_SUCCESS) {
} else {
}
return (rc);
default:
break;
}
}
}
/*ARGSUSED2*/
int
void *vcookie,
{
int rc;
for (;;) {
/*
* if the ldap connection being used is shared,
* ensure the thread-specific data area for setting
* status is allocated
*/
rc = __s_api_check_MTC_tsd();
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
switch (state) {
case PROCESS_RESULT:
return (NS_LDAP_SUCCESS);
case LDAP_ERROR:
ONE_STEP);
/* FALLTHROUGH */
case ERROR:
return (rc);
case EXIT:
return (NS_LDAP_SUCCESS);
}
}
}
int
void **vcookie,
{
int rc;
return (NS_LDAP_INVALID_PARAM);
/* Complete search */
/* Copy results back to user */
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
int
{
int i;
#ifdef DEBUG
#endif
return (NS_LDAP_INVALID_PARAM);
for (i = 0; i < res->entries_count; i++) {
}
}
return (NS_LDAP_SUCCESS);
}
/*ARGSUSED*/
int
const int flags,
{
int rc = 0;
int do_not_fail_if_new_pwd_reqd = 0;
int nopasswd_acct_mgmt = 0;
#ifdef DEBUG
#endif
if (!auth)
return (NS_LDAP_INVALID_PARAM);
(void) __ns_ldap_freeError(errorp);
if (connectionId > -1)
return (rc);
}
char **
{
int i;
return (NULL);
for (i = 0; i < entry->attr_count; i++) {
}
return (NULL);
}
{
int i;
return (NULL);
for (i = 0; i < entry->attr_count; i++) {
}
return (NULL);
}
/*ARGSUSED*/
int
__ns_ldap_uid2dn(const char *uid,
char **userDN,
{
char **value;
int rc = 0;
int i = 0;
return (NS_LDAP_INVALID_PARAM);
while (uid[i] != '\0') {
if (uid[i] == '=') {
return (NS_LDAP_SUCCESS);
}
i++;
}
i = 0;
i++;
if (uid[i] == '\0') {
return (NS_LDAP_MEMORY);
}
return (NS_LDAP_MEMORY);
}
} else {
return (NS_LDAP_MEMORY);
}
return (NS_LDAP_MEMORY);
}
}
/*
* we want to retrieve the DN as it appears in LDAP
* hence the use of NS_LDAP_NOT_CVT_DN in flags
*/
userdata);
if (rc != NS_LDAP_SUCCESS) {
if (result) {
(void) __ns_ldap_freeResult(&result);
}
return (rc);
}
(void) __ns_ldap_freeResult(&result);
NULL);
return (NS_LDAP_INTERNAL);
}
(void) __ns_ldap_freeResult(&result);
return (NS_LDAP_SUCCESS);
}
/*ARGSUSED*/
int
__ns_ldap_host2dn(const char *host,
const char *domain,
char **hostDN,
{
char **value;
int rc;
/*
* XXX
* the domain parameter needs to be used in case domain is not local, if
* this routine is to support multi domain setups, it needs lots of work...
*/
return (NS_LDAP_INVALID_PARAM);
return (NS_LDAP_MEMORY);
}
return (NS_LDAP_MEMORY);
}
/*
* we want to retrieve the DN as it appears in LDAP
* hence the use of NS_LDAP_NOT_CVT_DN in flags
*/
userdata);
if (rc != NS_LDAP_SUCCESS) {
if (result) {
(void) __ns_ldap_freeResult(&result);
}
return (rc);
}
(void) __ns_ldap_freeResult(&result);
NULL);
return (NS_LDAP_INTERNAL);
}
(void) __ns_ldap_freeResult(&result);
return (NS_LDAP_SUCCESS);
}
/*ARGSUSED*/
int
__ns_ldap_dn2domain(const char *dn,
char **domain,
{
return (NS_LDAP_INVALID_PARAM);
else
return (NS_LDAP_INVALID_PARAM);
/*
* break dn into rdns
*/
return (NS_LDAP_MEMORY);
return (NS_LDAP_INVALID_PARAM);
for (i = 0; rdns[i]; i++)
pnum = i;
if (newdn)
return (NS_LDAP_MEMORY);
}
/* construct a semi-normalized dn, newdn */
*newdn = '\0';
for (i = 0; rdns[i]; i++) {
__s_api_remove_rdn_space(rdns[i]));
}
/* remove the last ',' */
/*
* loop and find the domain name associated with newdn,
* removing rdn one by one from left to right
*/
for (i = 0; i < pnum; i++) {
if (*errorp)
(void) __ns_ldap_freeError(errorp);
/*
* try cache manager first
*/
if (rc != NS_LDAP_SUCCESS) {
/*
* try ldap server second
*/
} else {
/*
* skip the last one,
* since it is already cached by ldap_cachemgr
*/
i--;
}
if (rc == NS_LDAP_SUCCESS) {
if (__s_api_nscd_proc()) {
/*
* If it's nscd, ask cache manager to save the
* dn to domain mapping(s)
*/
for (j = 0; j <= i; j++) {
(void) __s_api_set_cachemgr_data(
dns[j],
*domain);
}
}
break;
}
}
if (rc != NS_LDAP_SUCCESS)
return (rc);
}
/*ARGSUSED*/
int
__ns_ldap_getServiceAuthMethods(const char *service,
{
int slen;
void **param;
return (NS_LDAP_INVALID_PARAM);
return (NS_LDAP_INVALID_PARAM);
return (rc);
}
cnt = 0;
continue;
continue;
srv++;
max++) {}
(void) __ns_ldap_freeParam(¶m);
return (NS_LDAP_MEMORY);
}
while (!done) {
*send = '\0';
send++;
}
if (i == -1) {
(void) __ns_ldap_freeParam(¶m);
gettext("Unsupported "
"serviceAuthenticationMethod: %s.\n"), srv);
return (NS_LDAP_CONFIG);
}
(void) __ns_ldap_freeParam(¶m);
return (NS_LDAP_MEMORY);
}
else
}
}
(void) __ns_ldap_freeParam(¶m);
return (NS_LDAP_SUCCESS);
}
/*
* This routine is called when certain scenario occurs
* e.g.
* service == auto_home
* SSD = automount: ou = mytest,
* NS_LDAP_MAPATTRIBUTE= auto_home: automountMapName=AAA
* NS_LDAP_OBJECTCLASSMAP= auto_home:automountMap=MynisMap
* NS_LDAP_OBJECTCLASSMAP= auto_home:automount=MynisObject
*
* The automountMapName is prepended implicitely but is mapped
* to AAA. So dn could appers as
* dn: AAA=auto_home,ou=bar,dc=foo,dc=com
* dn: automountKey=user_01,AAA=auto_home,ou=bar,dc=foo,dc=com
* dn: automountKey=user_02,AAA=auto_home,ou=bar,dc=foo,dc=com
* in the directory.
* This function is called to covert the mapped attr back to
* orig attr when the entries are searched and returned
*/
int
ns_ldap_error_t **errp) {
char *mapped_attr = NULL;
char *automountmapname = "automountMapName";
int rc = NS_LDAP_SUCCESS;
/*
*/
return (NS_LDAP_INVALID_PARAM);
/*
* Check to see if there is a mapped attribute for auto_xxx
*/
/*
* if no mapped attribute for auto_xxx, try automount
*/
"automount", automountmapname);
/*
* if no mapped attribute is found, return SUCCESS (no op)
*/
return (NS_LDAP_SUCCESS);
/*
* if the mapped attribute is found and attr is not empty,
* copy it
*/
if (mapped_attr == NULL) {
return (NS_LDAP_MEMORY);
}
} else {
"Attribute nisMapName is mapped to an "
"empty string.\n"));
return (NS_LDAP_CONFIG);
}
/*
* Locate the mapped attribute in the dn
* and replace it if it exists
*/
(const char *) automountmapname, (const char *) mapped_attr,
/* clean up */
/*
* If mapped attr is found(buffer != NULL)
* a new dn is returned
* If no mapped attribute is in dn,
* return NS_LDAP_SUCCESS (no op)
* If no memory,
* return NS_LDAP_MEMORY (no op)
*/
}
return (rc);
}
/*
* If the mapped attr is found in the dn,
* return NS_LDAP_SUCCESS and a new_dn.
* If no mapped attr is found,
* return NS_LDAP_SUCCESS and *new_dn == NULL
* If there is not enough memory,
* return NS_LDAP_MEMORY and *new_dn == NULL
*/
int
const char *orig_attr, const char *mapped_attr,
int i = 0, found = 0;
/*
* seperate dn into individual componets
* e.g.
* "automountKey=user_01" , "automountMapName_test=auto_home", ...
*/
/*
* This will find "mapped attr=value" in dn.
* It won't find match if mapped attr appears
* in the value.
*/
/*
* This function is called when reading from
* the directory so assume each component has "=".
* Any ill formatted dn should be rejected
* before adding to the directory
*/
*cur = '\0';
found = 1;
*cur = '=';
if (found) break;
}
if (!found) {
return (NS_LDAP_SUCCESS);
}
/*
* The new length is *dn length + (difference between
* orig attr and mapped attr) + 1 ;
* e.g.
* automountKey=aa,automountMapName_test=auto_home,dc=foo,dc=com
* ==>
* automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
*/
return (NS_LDAP_MEMORY);
}
/*
* Locate the mapped attr in the dn.
* Use dnArray[i] instead of mapped_attr
* because mapped_attr could appear in
* the value
*/
/* copy the portion before mapped attr in dn */
/*
* Copy the orig_attr. e.g. automountMapName
* This replaces mapped attr with orig attr
*/
/*
* Copy the portion after mapped attr in dn
*/
return (NS_LDAP_SUCCESS);
}
/*
* Validate Filter functions
*/
/* ***** Start of modified libldap.so.5 filter parser ***** */
/* filter parsing routine forward references */
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);
/*
* assumes string manipulation is in-line
* and all strings are sufficient in size
* return value is the position after 'c'
*/
static char *
{
char *ret;
*next = c;
return (ret);
return (ret);
}
static char *
find_right_paren(char *s)
{
balance = 1;
escape = 0;
while (*s && balance) {
if (escape == 0) {
if (*s == '(')
balance++;
else if (*s == ')')
balance--;
}
if (*s == '\\' && ! escape)
escape = 1;
else
escape = 0;
if (balance)
s++;
}
return (*s ? s : NULL);
}
static char *
adj_complex_filter(char *str)
{
char *next;
/*
* We have (x(filter)...) with str sitting on
* the x. We have to find the paren matching
* the one before the x and put the intervening
* filters by calling adj_filter_list().
*/
str++;
return (NULL);
*next = '\0';
return (NULL);
next++;
return (next);
}
static int
adj_filter(char *str)
{
char *next;
parens = 0;
while (*str) {
switch (*str) {
case '(':
str++;
parens++;
switch (*str) {
case '&':
return (-1);
parens--;
break;
case '|':
return (-1);
parens--;
break;
case '!':
return (-1);
parens--;
break;
case '(':
/* illegal ((case - generated by conversion */
/* find missing close) */
/* error if not found */
return (-1);
/* remove redundant (and) */
}
cp++;
while (*cp)
*dp = '\0';
/* re-start test at original ( */
parens--;
str--;
break;
default:
balance = 1;
escape = 0;
if (escape == 0) {
if (*next == '(')
balance++;
else if (*next == ')')
balance--;
}
escape = 1;
else
escape = 0;
if (balance)
next++;
}
if (balance != 0)
return (-1);
*next = '\0';
return (-1);
}
next++;
parens--;
break;
}
break;
case ')':
str++;
parens--;
break;
case ' ':
str++;
break;
default: /* assume it's a simple type=value filter */
return (-1);
}
break;
}
}
return (parens ? -1 : 0);
}
/*
* Put a list of filters like this "(filter1)(filter2)..."
*/
static int
adj_filter_list(char *str)
{
char *next;
char save;
while (*str) {
str++;
if (*str == '\0')
break;
return (-1);
/* now we have "(filter)" with str pointing to it */
*next = '\0';
return (-1);
}
return (0);
}
/*
* is_valid_attr - returns 1 if a is a syntactically valid left-hand side
* of a filter expression, 0 otherwise. A valid string may contain only
* letters, numbers, hyphens, semi-colons, colons and periods. examples:
* cn
* cn;lang-fr
* 1.2.3.4;binary;dynamic
* mail;dynamic
* cn:dn:1.2.3.4
*
* For compatibility with older servers, we also allow underscores in
* attribute types, even through they are not allowed by the LDAPv3 RFCs.
*/
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; /* valid */
default:
return (0);
}
}
}
return (1);
}
static char *
find_star(char *s)
{
for (; *s; ++s) {
switch (*s) {
case '*':
return (s);
case '\\':
++s;
++s;
default:
break;
}
}
return (NULL);
}
static int
adj_simple_filter(char *str)
{
char *value;
int ftype = 0;
int rc;
return (rc);
}
goto free_and_return;
}
value = s + 1;
*s-- = '\0';
filterop = *s;
filterop == ':') {
*s = '\0';
}
if (! is_valid_attr(str)) {
goto free_and_return;
}
switch (filterop) {
case '<': /* LDAP_FILTER_LE */
case '>': /* LDAP_FILTER_GE */
case '~': /* LDAP_FILTER_APPROX */
break;
case ':': /* extended filter - v3 only */
/*
* extended filter looks like this:
*
* [type][':dn'][':'oid]':='value
*
* where one of type or :oid is required.
*
*/
goto free_and_return;
}
*s2 = '\0';
} else {
*s2 = '\0';
goto free_and_return;
}
*s3 = '\0';
}
}
if (unescape_filterval(value) < 0) {
goto free_and_return;
}
rc = 0;
goto free_and_return;
/* break; */
default:
ftype = 0; /* LDAP_FILTER_EQUALITY */
} else {
goto free_and_return;
}
break;
}
if (ftype != 0) { /* == LDAP_FILTER_PRESENT */
rc = 0;
} else if (unescape_filterval(value) >= 0) {
rc = 0;
}
if (rc != -1) {
rc = 0;
}
return (rc);
}
/*
* Check in place both LDAPv2 (RFC-1960) and LDAPv3 (hexadecimal) escape
* sequences within the null-terminated string 'val'.
*
* If 'val' contains invalid escape sequences we return -1.
* Otherwise return 1
*/
static int
unescape_filterval(char *val)
{
int escape, firstdigit;
char *s;
firstdigit = 0;
escape = 0;
for (s = val; *s; s++) {
if (escape) {
/*
* first try LDAPv3 escape (hexadecimal) sequence
*/
if (hexchar2int(*s) < 0) {
if (firstdigit) {
/*
* LDAPv2 (RFC1960) escape sequence
*/
escape = 0;
} else {
return (-1);
}
}
if (firstdigit) {
firstdigit = 0;
} else {
escape = 0;
}
} else if (*s != '\\') {
escape = 0;
} else {
escape = 1;
firstdigit = 1;
}
}
return (1);
}
/*
* convert character 'c' that represents a hexadecimal digit to an integer.
* if 'c' is not a hexidecimal digit [0-9A-Fa-f], -1 is returned.
* otherwise the converted value is returned.
*/
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;
*nextstar++ = '\0';
}
if (*val != '\0') {
if (unescape_filterval(val) < 0) {
return (-1);
}
}
}
return (0);
}
/* ***** End of modified libldap.so.5 filter parser ***** */
/*
* Walk filter, remove redundant parentheses in-line
* verify that the filter is reasonable
*/
static int
{
int rc;
/* Parse filter looking for illegal values */
if (rc != 0) {
return (NS_LDAP_OP_FAILED);
}
/* end of filter checking */
return (NS_LDAP_SUCCESS);
}
/*
* Set the account management request control that needs to be sent to server.
* This control is required to get the account management information of
* a user to do local account checking.
*/
static int
{
return (NS_LDAP_MEMORY);
/* fill in the fields of this new control */
return (NS_LDAP_MEMORY);
}
if (requestctrls == NULL) {
return (NS_LDAP_MEMORY);
}
requestctrls[0] = req;
return (NS_LDAP_SUCCESS);
}
/*
* int get_new_acct_more_info(BerElement *ber,
* AcctUsableResponse_t *acctResp)
*
* Decode the more_info data from an Account Management control response,
* when the account is not usable and when code style is from recent LDAP
* servers (see below comments for parse_acct_cont_resp_msg() to get more
* details on coding styles and ASN1 description).
*
* Expected BER encoding: {tbtbtbtiti}
* +t: tag is 0
* +b: TRUE if inactive due to account inactivation
* +t: tag is 1
* +b: TRUE if password has been reset
* +t: tag is 2
* +b: TRUE if password is expired
* +t: tag is 3
* +i: contains num of remaining grace, 0 means no grace
* +t: tag is 4
* +i: contains num of seconds before auto-unlock. -1 means acct is locked
* forever (i.e. until reset)
*
* Asumptions:
* - ber is not null
* - acctResp is not null and is initialized with default values for the
* fields in its AcctUsableResp.more_info structure
* - the ber stream is received in the correct order, per the ASN1 description.
* We do not check this order and make the asumption that it is correct.
* Note that the ber stream may not (and will not in most cases) contain
* all fields.
*/
static int
{
int rc = NS_LDAP_SUCCESS;
char *last;
int berRC = 0;
/*
* look at each of them 1 by 1, without checking on their order
* and possible multi values.
*/
berRC = 0;
switch (rTag) {
case 0 | LBER_CLASS_CONTEXT | LBER_PRIMITIVE:
/* inactive */
if (berRC != LBER_ERROR) {
}
break;
/* reset */
if (berRC != LBER_ERROR) {
= (rValue != 0) ? 1 : 0;
}
break;
/* expired */
if (berRC != LBER_ERROR) {
= (rValue != 0) ? 1 : 0;
}
break;
/* remaining grace */
if (berRC != LBER_ERROR) {
= rValue;
}
break;
/* seconds before unlock */
if (berRC != LBER_ERROR) {
}
break;
default :
break;
}
if (berRC == LBER_ERROR) {
gettext("error 0x%x decoding value for "
}
if (rc != NS_LDAP_SUCCESS) {
/* exit the for loop */
break;
}
}
return (rc);
}
/*
* int get_old_acct_opt_more_info(BerElement *ber,
* AcctUsableResponse_t *acctResp)
*
* Decode the optional more_info data from an Account Management control
* response, when the account is not usable and when code style is from LDAP
* server 5.2p4 (see below comments for parse_acct_cont_resp_msg() to get more
* details on coding styles and ASN1 description).
*
* Expected BER encoding: titi}
* +t: tag is 2
* +i: contains num of remaining grace, 0 means no grace
* +t: tag is 3
* +i: contains num of seconds before auto-unlock. -1 means acct is locked
* forever (i.e. until reset)
*
* Asumptions:
* - ber is a valid BER element
* - acctResp is initialized for the fields in its AcctUsableResp.more_info
* structure
*/
static int
{
int rc = NS_LDAP_SUCCESS;
int rem_grace, sec_b4_unlock;
switch (tag) {
case 2:
/* decode and maybe 3 is following */
"rem_grace"));
break;
}
/* this is a success case, break to exit */
"optional data"));
break;
}
if (tag == 3) {
gettext("Can not get sec_b4_unlock "
"- 1st case"));
break;
}
} else { /* unknown tag */
"- 1st case"));
break;
}
break;
case 3:
"sec_b4_unlock - 2nd case"));
break;
}
break;
default: /* unknown tag */
break;
}
return (rc);
}
/*
* **** This function needs to be moved to libldap library ****
* parse_acct_cont_resp_msg() parses the message received by server according to
* following format (ASN1 notation):
*
* ACCOUNT_USABLE_RESPONSE::= CHOICE {
* is_available [0] INTEGER,
* ** seconds before expiration **
* is_not_available [1] more_info
* }
* more_info::= SEQUENCE {
* inactive [0] BOOLEAN DEFAULT FALSE,
* reset [1] BOOLEAN DEFAULT FALSE,
* expired [2] BOOLEAN DEFAULT FALSE,
* remaining_grace [3] INTEGER OPTIONAL,
* seconds_before_unlock [4] INTEGER OPTIONAL
* }
*/
/*
* #define used to make the difference between coding style as done
* by LDAP server 5.2p4 and newer LDAP servers. There are 4 values:
* - DS52p4_USABLE: 5.2p4 coding style, account is usable
* - DS52p4_NOT_USABLE: 5.2p4 coding style, account is not usable
* - NEW_USABLE: newer LDAP servers coding style, account is usable
* - NEW_NOT_USABLE: newer LDAP servers coding style, account is not usable
*
* An account would be considered not usable if for instance:
* - it's been made inactive in the LDAP server
* - or its password was reset in the LDAP server database
* - or its password expired
* - or the account has been locked, possibly forever
*/
#define DS52p4_USABLE 0x00
#define DS52p4_NOT_USABLE 0x01
static int
{
int rc = NS_LDAP_SUCCESS;
int i;
/* used for any coding style when account is usable */
/* used for 5.2p4 coding style when account is not usable */
return (NS_LDAP_INVALID_PARAM);
}
== 0) {
break;
}
}
/* Ldap control is not found */
"not found"));
return (NS_LDAP_NOTFOUND);
}
/* Allocate a BER element from the control value and parse it. */
return (NS_LDAP_MEMORY);
/* Ldap decoding error */
return (NS_LDAP_INTERNAL);
}
switch (tag) {
case DS52p4_USABLE:
case NEW_USABLE:
== LBER_ERROR) {
/* Ldap decoding error */
"seconds_before_expiry"));
break;
}
/* ber_scanf() succeeded */
break;
case DS52p4_NOT_USABLE:
== LBER_ERROR) {
/* Ldap decoding error */
break;
}
/* ber_scanf() succeeded */
((inactive == 0) ? 0 : 1);
((reset == 0) ? 0 : 1);
((expired == 0) ? 0 : 1);
/* this is a success case, break to exit */
break;
}
/*
* left to be decoded.
*/
break;
case NEW_NOT_USABLE:
/*
* Recent LDAP servers won't code more_info data for default
* values (see above comments on ASN1 description for what
* fields have default values & what fields are optional).
*/
if (len == 0) {
/*
* Nothing else to decode; this is valid and we
* use default values set above.
*/
"empty, using default values"));
break;
}
/*
* be decoded.
*/
break;
default:
"(tag: 0x%x)"), tag);
break;
}
return (rc);
}
/*
* __ns_ldap_getAcctMgmt() is called from pam account management stack
* for retrieving accounting information of users with no user password -
* eg. rlogin, rsh, etc. This function uses the account management control
* request to do a search on the server for the user in question. The
* response control returned from the server is got from the cookie.
* Input params: username of whose account mgmt information is to be got
* pointer to hold the parsed account management information
* Return values: NS_LDAP_SUCCESS on success or appropriate error
* code on failure
*/
int
{
char ldapfilter[1024];
char service[] = "shadow";
return (NS_LDAP_INVALID_PARAM);
/* Initialize State machine cookie */
return (NS_LDAP_MEMORY);
/* see if need to follow referrals */
if (rc != NS_LDAP_SUCCESS) {
(void) __ns_ldap_freeError(&error);
goto out;
}
/* get the service descriptor - or create a default one */
if (rc != NS_LDAP_SUCCESS) {
(void) __ns_ldap_freeError(&error);
goto out;
}
/* Create default service Desc */
sizeof (ns_ldap_search_desc_t *));
rc = NS_LDAP_MEMORY;
goto out;
}
dptr = (ns_ldap_search_desc_t *)
rc = NS_LDAP_MEMORY;
goto out;
}
/* default base */
if (rc != NS_LDAP_SUCCESS) {
if (dns) {
}
goto out;
}
if (dns) {
}
rc = NS_LDAP_MEMORY;
goto out;
}
/* default scope */
scope = 0;
}
rc = NS_LDAP_MEMORY;
goto out;
}
/* search for entries for this particular uid */
rc = NS_LDAP_MEMORY;
goto out;
}
/* create the control request */
goto out;
/* Process search */
/* Copy results back to user */
if (rc != NS_LDAP_SUCCESS)
goto out;
!= NS_LDAP_SUCCESS)
goto out;
out:
return (rc);
}