summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsldap
diff options
context:
space:
mode:
authorMichen Chang <Michen.Chang@Sun.COM>2009-02-13 18:18:56 -0800
committerMichen Chang <Michen.Chang@Sun.COM>2009-02-13 18:18:56 -0800
commitdd1104fbe0f0f41434502f335b9f0b34999f771c (patch)
tree57c95d64bc40cebf2b145329e1f49e811352d502 /usr/src/lib/libsldap
parentd68ef20e3fe871e73146fc684d29d335521dcd99 (diff)
downloadillumos-joyent-dd1104fbe0f0f41434502f335b9f0b34999f771c.tar.gz
PSARC 2008/745 nss_ldap shadowAccount support
6715171 nss_ldap and passwdutil do not support all shadowAccount attributes 6797378 'ldapaddent -d passwd' does not print 'x' for the password field 6783712 libsldap fails to set correct version number for V1 profile
Diffstat (limited to 'usr/src/lib/libsldap')
-rw-r--r--usr/src/lib/libsldap/common/mapfile-vers34
-rw-r--r--usr/src/lib/libsldap/common/ns_cache_door.h14
-rw-r--r--usr/src/lib/libsldap/common/ns_config.c79
-rw-r--r--usr/src/lib/libsldap/common/ns_confmgr.c56
-rw-r--r--usr/src/lib/libsldap/common/ns_internal.h11
-rw-r--r--usr/src/lib/libsldap/common/ns_sldap.h27
-rw-r--r--usr/src/lib/libsldap/common/ns_writes.c308
7 files changed, 473 insertions, 56 deletions
diff --git a/usr/src/lib/libsldap/common/mapfile-vers b/usr/src/lib/libsldap/common/mapfile-vers
index f58a9328d4..e043513adf 100644
--- a/usr/src/lib/libsldap/common/mapfile-vers
+++ b/usr/src/lib/libsldap/common/mapfile-vers
@@ -22,19 +22,6 @@
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-
-#
-# MAPFILE HEADER START
-#
-# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
-# Object versioning must comply with the rules detailed in
-#
-# usr/src/lib/README.mapfiles
-#
-# You should not be making modifications here until you've read the most current
-# copy of that file. If you need help, contact a gatekeeper for guidance.
-#
-# MAPFILE HEADER END
#
# There really should be only one SUNWprivate version.
@@ -42,22 +29,23 @@
SUNWprivate_1.1 {
global:
- __ns_ldap_initStandalone;
- __ns_ldap_getConnectionInfoFromDUA;
- __ns_ldap_getRootDSE;
- __ns_ldap_pingOfflineServers;
__ns_ldap_cancelStandalone;
- __ns_ldap_initAuth;
+ __ns_ldap_check_all_preq;
+ __ns_ldap_check_dns_preq;
+ __ns_ldap_check_gssapi_preq;
__ns_ldap_getAcctMgmt;
- __s_api_get_canonical_name;
__ns_ldap_getAttrStruct;
+ __ns_ldap_getConnectionInfoFromDUA;
+ __ns_ldap_getRootDSE;
+ __ns_ldap_initAuth;
+ __ns_ldap_initStandalone;
+ __ns_ldap_is_shadow_update_enabled;
+ __ns_ldap_pingOfflineServers;
__ns_ldap_self_gssapi_config;
__ns_ldap_self_gssapi_only_set;
- __ns_ldap_check_dns_preq;
- __ns_ldap_check_gssapi_preq;
- __ns_ldap_check_all_preq;
- __s_api_ip2hostname;
+ __s_api_get_canonical_name;
__s_api_hostname2ip;
+ __s_api_ip2hostname;
} SUNWprivate_1.0;
SUNWprivate_1.0 {
diff --git a/usr/src/lib/libsldap/common/ns_cache_door.h b/usr/src/lib/libsldap/common/ns_cache_door.h
index 391394cbe7..52599534af 100644
--- a/usr/src/lib/libsldap/common/ns_cache_door.h
+++ b/usr/src/lib/libsldap/common/ns_cache_door.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _NS_CACHE_DOOR_H
#define _NS_CACHE_DOOR_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Definitions for client side of doors-based ldap caching
*/
@@ -96,6 +94,13 @@ typedef struct ldap_config_out {
char config_str[sizeof (int)]; /* real size is data_size */
} ldap_config_out_t;
+typedef struct ldap_admin_mod_result {
+ uint32_t ns_err; /* ns_ldap error code */
+ uint32_t status; /* error status */
+ uint32_t msg_size; /* length of error message */
+ char msg[sizeof (int)]; /* real size is msg_size */
+} ldap_admin_mod_result_t;
+
/*
* structure returned by server for all calls
*/
@@ -116,6 +121,7 @@ typedef struct {
ldap_strlist_t strlist;
ldap_config_out_t config_str;
ldap_get_change_out_t changes;
+ ldap_admin_mod_result_t admin_result;
} ldap_u;
} ldap_return_t;
@@ -187,6 +193,8 @@ typedef union {
#define GETCACHESTAT 24
/* Configuration change or server status change notification */
#define GETSTATUSCHANGE 25
+ /* perform admin modify via ldap_cachemgr */
+#define ADMINMODIFY 26
/*
* GETLDAPSERVER request flags
diff --git a/usr/src/lib/libsldap/common/ns_config.c b/usr/src/lib/libsldap/common/ns_config.c
index 2046a46bad..1a7a21bfee 100644
--- a/usr/src/lib/libsldap/common/ns_config.c
+++ b/usr/src/lib/libsldap/common/ns_config.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* libsldap - library side configuration components
* Routines to manage the config structure
@@ -202,6 +200,12 @@ static ns_enum_map ns_pref_enum[] = {
{ -1, NULL },
};
+static ns_enum_map ns_shadow_update_enum[] = {
+ { ENUM2INT(NS_LDAP_ENABLE_SHADOW_UPDATE_FALSE), "FALSE" },
+ { ENUM2INT(NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE), "TRUE" },
+ { -1, NULL },
+};
+
static int ns_def_auth_v1[] = {
ENUM2INT(NS_LDAP_EA_NONE),
0
@@ -392,11 +396,31 @@ static ns_default_config defconfig[] = {
NULL, /* not defined in the Profile */
{ CHARPTR, 0, NULL },
__s_val_binddn, NULL },
+
{"NS_LDAP_BINDPASSWD", NS_LDAP_BINDPASSWD_P,
CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
NULL, /* not defined in the Profile */
{ CHARPTR, 0, NULL },
__s_val_bindpw, NULL },
+
+ {"NS_LDAP_ENABLE_SHADOW_UPDATE", NS_LDAP_ENABLE_SHADOW_UPDATE_P,
+ CREDCONFIG, INT, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { INT, 0, INT2VOIDPTR(NS_LDAP_ENABLE_SHADOW_UPDATE_FALSE) },
+ NULL, ns_shadow_update_enum },
+
+ {"NS_LDAP_ADMIN_BINDDN", NS_LDAP_ADMIN_BINDDN_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, NULL },
+ __s_val_binddn, NULL },
+
+ {"NS_LDAP_ADMIN_BINDPASSWD", NS_LDAP_ADMIN_BINDPASSWD_P,
+ CREDCONFIG, CHARPTR, TRUE, NS_LDAP_V2,
+ NULL, /* not defined in the Profile */
+ { CHARPTR, 0, NULL },
+ __s_val_bindpw, NULL },
+
{"NS_LDAP_EXP", NS_LDAP_EXP_P,
SERVERCONFIG, TIMET, TRUE, NS_LDAP_V2,
NULL, /* initialized by code to time+NS_LDAP_CACHETTL */
@@ -601,6 +625,9 @@ __s_get_enum_value(ns_config_t *ptr, char *value, ParamIndexType i)
case NS_LDAP_PREF_ONLY_P:
mapp = &ns_pref_enum[0];
break;
+ case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
+ mapp = &ns_shadow_update_enum[0];
+ break;
case NS_LDAP_CREDENTIAL_LEVEL_P:
if (ptr->version == NS_LDAP_V1)
return (-1);
@@ -713,6 +740,21 @@ __s_get_searchref_name(ns_config_t *ptr, SearchRef_t type)
return ("Unknown SearchRef_t type specified");
}
+char *
+__s_get_shadowupdate_name(enableShadowUpdate_t type)
+{
+ register ns_enum_map *mapp;
+
+ mapp = &ns_shadow_update_enum[0];
+
+ for (; mapp->name != NULL; mapp++) {
+ if (type == INT2SHADOWUPDATENUM(mapp->value)) {
+ return (mapp->name);
+ }
+ }
+ return ("Unknown enableShadowUpdate_t type specified");
+}
+
static char *
__s_get_credlvl_name(ns_config_t *ptr, CredLevel_t type)
{
@@ -1486,6 +1528,8 @@ verify_value(ns_config_t *cfg, char *name, char *value, char *errstr)
case NS_LDAP_CERT_NICKNAME_P:
case NS_LDAP_BINDDN_P:
case NS_LDAP_BINDPASSWD_P:
+ case NS_LDAP_ADMIN_BINDDN_P:
+ case NS_LDAP_ADMIN_BINDPASSWD_P:
case NS_LDAP_DOMAIN_P:
case NS_LDAP_SEARCH_BASEDN_P:
case NS_LDAP_SEARCH_TIME_P:
@@ -1648,6 +1692,7 @@ __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type,
case NS_LDAP_PREF_ONLY_P:
case NS_LDAP_SEARCH_REF_P:
case NS_LDAP_SEARCH_SCOPE_P:
+ case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
i = __s_get_enum_value(ptr, cp, def->index);
if (i < 0) {
(void) snprintf(errstr, sizeof (errstr),
@@ -2615,7 +2660,8 @@ __ns_ldap_setParamValue(ns_config_t *ptr, const ParamIndexType type,
*
* Init NS_LDAP_EXP_P here when CACHETTL is updated
*/
- if (type == NS_LDAP_BINDPASSWD_P) {
+ if (type == NS_LDAP_BINDPASSWD_P ||
+ type == NS_LDAP_ADMIN_BINDPASSWD_P) {
cp = conf.ns_pc;
cp2 = evalue((char *)cp);
conf.ns_pc = cp2;
@@ -3219,6 +3265,11 @@ __s_api_strValue(ns_config_t *cfg, char *str,
__s_get_scope_name(cfg,
(ScopeType_t)ptr->ns_i));
break;
+ case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
+ (void) strlcat(buf,
+ __s_get_shadowupdate_name(
+ (enableShadowUpdate_t)ptr->ns_i), bufsz);
+ break;
default:
(void) snprintf(ibuf, sizeof (ibuf),
"%d", ptr->ns_i);
@@ -3730,15 +3781,21 @@ static int
__s_val_binddn(ParamIndexType i, ns_default_config *def,
ns_param_t *param, char *errbuf)
{
+ char *dntype;
+
if (param && param->ns_ptype == CHARPTR &&
- i == NS_LDAP_BINDDN_P &&
+ (i == NS_LDAP_BINDDN_P || i == NS_LDAP_ADMIN_BINDDN_P) &&
((param->ns_pc == NULL) ||
((*(param->ns_pc) != '\0') &&
(strchr(param->ns_pc, '=') != NULL)))) {
return (NS_SUCCESS);
}
+ if (i == NS_LDAP_BINDDN_P)
+ dntype = "proxy";
+ else
+ dntype = "update";
(void) snprintf(errbuf, MAXERROR,
- gettext("NULL or invalid proxy bind DN"));
+ gettext("NULL or invalid %s bind DN"), dntype);
return (NS_PARSE_ERR);
}
@@ -3751,14 +3808,20 @@ static int
__s_val_bindpw(ParamIndexType i, ns_default_config *def,
ns_param_t *param, char *errbuf)
{
+ char *pwtype;
+
if (param && param->ns_ptype == CHARPTR &&
- i == NS_LDAP_BINDPASSWD_P &&
+ (i == NS_LDAP_BINDPASSWD_P || i == NS_LDAP_ADMIN_BINDPASSWD_P) &&
((param->ns_pc == NULL) ||
(*(param->ns_pc) != '\0'))) {
return (NS_SUCCESS);
}
+ if (i == NS_LDAP_BINDPASSWD_P)
+ pwtype = "proxy";
+ else
+ pwtype = "admin";
(void) snprintf(errbuf, MAXERROR,
- gettext("NULL proxy bind password"));
+ gettext("NULL %s bind password"), pwtype);
return (NS_PARSE_ERR);
}
diff --git a/usr/src/lib/libsldap/common/ns_confmgr.c b/usr/src/lib/libsldap/common/ns_confmgr.c
index 1fd58aac6f..a96f186ded 100644
--- a/usr/src/lib/libsldap/common/ns_confmgr.c
+++ b/usr/src/lib/libsldap/common/ns_confmgr.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* libsldap - cachemgr side configuration components */
#include <stdio.h>
@@ -332,6 +330,15 @@ __s_api_create_config_door_str(char *config, ns_ldap_error_t **errorp)
__s_api_destroy_config(configStruct);
return (NULL);
}
+ } else if (strcasecmp(attrVal,
+ _PROFILE1_OBJECTCLASS) == 0) {
+ if (__ns_ldap_setParamValue(configStruct,
+ NS_LDAP_FILE_VERSION_P,
+ NS_LDAP_VERSION_1,
+ errorp) != NS_LDAP_SUCCESS) {
+ __s_api_destroy_config(configStruct);
+ return (NULL);
+ }
}
continue;
}
@@ -490,6 +497,10 @@ __ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname, ns_config_t *new)
}
(void) memset((char *)configinfo, 0, sizeof (LineBuf));
for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
+ /* the credential for shadow update is not to be exposed */
+ if (i == NS_LDAP_ADMIN_BINDDN_P ||
+ i == NS_LDAP_ADMIN_BINDPASSWD_P)
+ continue;
str = __s_api_strValue(ptr, string, sizeof (string), i,
NS_DOOR_FMT);
if (str == NULL)
@@ -628,10 +639,15 @@ __ns_ldap_DumpLdif(char *filename)
if (str == NULL)
continue;
/*
- * don't dump binddn, bind password, or cert path as they
- * are not part of version 2 profiles
+ * don't dump binddn, bind password, admin binddn, admin
+ * bind password, enableShadowUpdate flag, or cert path
+ * as they are not part of version 2 profiles
*/
- if ((i != NS_LDAP_BINDDN_P) && (i != NS_LDAP_BINDPASSWD_P) &&
+ if ((i != NS_LDAP_BINDDN_P) &&
+ (i != NS_LDAP_BINDPASSWD_P) &&
+ (i != NS_LDAP_ADMIN_BINDDN_P) &&
+ (i != NS_LDAP_ADMIN_BINDPASSWD_P) &&
+ (i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) &&
(i != NS_LDAP_HOST_CERTPATH_P))
(void) fprintf(fp, "%s\n", str);
if (str != (char *)&string[0]) {
@@ -922,6 +938,7 @@ __ns_ldap_make_config(ns_ldap_result_t *result)
}
}
if (ptr->version != NS_LDAP_V1) {
+ ParamIndexType i;
if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) {
(void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P,
curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc,
@@ -934,6 +951,28 @@ __ns_ldap_make_config(ns_ldap_result_t *result)
curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc,
&error);
}
+ i = NS_LDAP_ENABLE_SHADOW_UPDATE_P;
+ if (curr_ptr->paramList[i].ns_ptype == INT) {
+ char *val;
+ val = __s_get_shadowupdate_name(
+ curr_ptr->paramList[i].ns_i);
+ (void) __ns_ldap_setParamValue(ptr, i, val, &error);
+ }
+ if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype ==
+ CHARPTR) {
+ (void) __ns_ldap_setParamValue(ptr,
+ NS_LDAP_ADMIN_BINDDN_P,
+ curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc,
+ &error);
+ }
+ if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype ==
+ CHARPTR) {
+ (void) __ns_ldap_setParamValue(ptr,
+ NS_LDAP_ADMIN_BINDPASSWD_P,
+ curr_ptr->
+ paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc,
+ &error);
+ }
if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype ==
CHARPTR) {
(void) __ns_ldap_setParamValue(ptr,
@@ -1065,6 +1104,11 @@ __ns_ldap_print_config(int verbose)
if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1))
continue;
+ /* the credential for shadow update is not to be exposed */
+ if (i == NS_LDAP_ADMIN_BINDDN_P ||
+ i == NS_LDAP_ADMIN_BINDPASSWD_P)
+ continue;
+
str = __s_api_strValue(ptr, string, BUFSIZ, i, NS_FILE_FMT);
if (str == NULL)
continue;
diff --git a/usr/src/lib/libsldap/common/ns_internal.h b/usr/src/lib/libsldap/common/ns_internal.h
index a7dbf4e6de..9adba43565 100644
--- a/usr/src/lib/libsldap/common/ns_internal.h
+++ b/usr/src/lib/libsldap/common/ns_internal.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -27,8 +27,6 @@
#ifndef _NS_INTERNAL_H
#define _NS_INTERNAL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -118,6 +116,11 @@ extern "C" {
/* max rdn length in conversion routines used by __ns_ldap_addTypedEntry() */
#define RDNSIZE 256
+/*
+ * special service used by ldap_cachemgr to indicate a shadow update
+ * is to be done with the credential of the administrator identity
+ */
+#define NS_ADMIN_SHADOW_UPDATE "shadow__admin_update"
/* Phase 1 profile information */
#define _PROFILE1_OBJECTCLASS "SolarisNamingProfile"
@@ -316,6 +319,7 @@ typedef struct ns_enum_map {
#define INT2SECENUM(x) ((TlsType_t)(x))
#define INT2PREFONLYENUM(x) ((PrefOnly_t)(x))
#define INT2CREDLEVELENUM(x) ((CredLevel_t)(x))
+#define INT2SHADOWUPDATENUM(x) ((enableShadowUpdate_t)(x))
#define INT2LDAPRETURN(x) ((ns_ldap_return_code)(x))
#define INT2CONFIGRETURN(x) ((ns_ldap_config_return_code)(x))
@@ -736,6 +740,7 @@ char *__s_get_security_name(ns_config_t *ptr, TlsType_t type);
char *__s_get_scope_name(ns_config_t *ptr, ScopeType_t type);
char *__s_get_pref_name(PrefOnly_t type);
char *__s_get_searchref_name(ns_config_t *ptr, SearchRef_t type);
+char *__s_get_shadowupdate_name(enableShadowUpdate_t type);
char *__s_get_hostcertpath(void);
void __s_api_free_sessionPool();
int __s_api_requestServer(const char *request, const char *server,
diff --git a/usr/src/lib/libsldap/common/ns_sldap.h b/usr/src/lib/libsldap/common/ns_sldap.h
index af288c5cf2..f8bb420019 100644
--- a/usr/src/lib/libsldap/common/ns_sldap.h
+++ b/usr/src/lib/libsldap/common/ns_sldap.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -84,6 +84,13 @@ typedef enum ScopeType {
#define NS_LDAP_NOT_CVT_DN 0x2000
/*
+ * NS_LDAP_UPDATE_SHADOW is for a privileged caller of the
+ * __ns_ldap_repAttr() to update the shadow database on the
+ * LDAP server.
+ */
+#define NS_LDAP_UPDATE_SHADOW 0x4000
+
+/*
* Authentication Information
*/
typedef enum CredLevel {
@@ -126,6 +133,11 @@ typedef enum PrefOnly {
NS_LDAP_PREF_TRUE = 1
} PrefOnly_t;
+typedef enum enableShadowUpdate {
+ NS_LDAP_ENABLE_SHADOW_UPDATE_FALSE = 0,
+ NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE = 1
+} enableShadowUpdate_t;
+
typedef struct UnixCred {
char *userID; /* Unix ID number */
char *passwd; /* password */
@@ -199,12 +211,15 @@ typedef enum {
NS_LDAP_SERVICE_AUTH_METHOD_P = 25,
NS_LDAP_SERVICE_CRED_LEVEL_P = 26,
NS_LDAP_HOST_CERTPATH_P = 27,
+ NS_LDAP_ENABLE_SHADOW_UPDATE_P = 28,
+ NS_LDAP_ADMIN_BINDDN_P = 29,
+ NS_LDAP_ADMIN_BINDPASSWD_P = 30,
/*
* The following entry (max ParamIndexType) is an internal
* placeholder. It must be the last (and highest value)
* entry in this eNum. Please update accordingly.
*/
- NS_LDAP_MAX_PIT_P = 28
+ NS_LDAP_MAX_PIT_P = 31
} ParamIndexType;
@@ -484,6 +499,11 @@ typedef struct ns_ldap_objectclass_map {
char *mappedOC; /* mapped objectclass */
} ns_ldap_objectclass_map_t;
+/*
+ * Value of the userPassword attribute representing NO Unix password
+ */
+#define NS_LDAP_NO_UNIX_PASSWORD "<NO UNIX PASSWORD>"
+
/* Opaque handle for batch API */
typedef struct ns_ldap_list_batch ns_ldap_list_batch_t;
@@ -872,6 +892,9 @@ int __ns_ldap_getParamType(
int __ns_ldap_getAcctMgmt(
const char *user,
AcctUsableResponse_t *acctResp);
+
+boolean_t __ns_ldap_is_shadow_update_enabled();
+
void
__ns_ldap_self_gssapi_only_set(
int flag);
diff --git a/usr/src/lib/libsldap/common/ns_writes.c b/usr/src/lib/libsldap/common/ns_writes.c
index 3abbefd829..14727d8a6b 100644
--- a/usr/src/lib/libsldap/common/ns_writes.c
+++ b/usr/src/lib/libsldap/common/ns_writes.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -38,10 +36,13 @@
#include <lber.h>
#include <ldap.h>
#include <syslog.h>
+#include <stddef.h>
+#include <sys/mman.h>
#include "ns_sldap.h"
#include "ns_internal.h"
#include "ns_connmgmt.h"
+#include "ns_cache_door.h"
/* Additional headers for addTypedEntry Conversion routines */
#include <pwd.h>
@@ -60,7 +61,8 @@
#include <sys/tsol/tndb.h>
#include <tsol/label.h>
-
+static int send_to_cachemgr(const char *,
+ ns_ldap_attr_t **, ns_ldap_error_t **);
/*
* If the rdn is a mapped attr:
* return NS_LDAP_SUCCESS and a new_dn.
@@ -1038,8 +1040,8 @@ write_state_machine(
errmsg = NULL;
}
- (void) sprintf(errstr,
- gettext(ldap_err2string(Errno)));
+ (void) snprintf(errstr, sizeof (errstr),
+ "%s", ldap_err2string(Errno));
err = strdup(errstr);
if (pwd_status != NS_PASSWD_GOOD) {
MKERROR_PWD_MGMT(*errorp, Errno, err,
@@ -1157,6 +1159,89 @@ __ns_ldap_delAttr(
return (rc);
}
+/* Retrieve the admin bind password from the configuration, if allowed. */
+static int
+get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
+{
+ void **paramVal = NULL;
+ int rc, ldaprc;
+ char *modparamVal = NULL;
+
+ /*
+ * For GSSAPI/Kerberos, host credential is used, no need to get
+ * admin bind password
+ */
+ if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
+ return (NS_LDAP_SUCCESS);
+
+ /*
+ * Retrieve admin bind password.
+ * The admin bind password is available
+ * only in the ldap_cachemgr process as
+ * they are not exposed outside of that
+ * process.
+ */
+ paramVal = NULL;
+ if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
+ &paramVal, errorp)) != NS_LDAP_SUCCESS)
+ return (ldaprc);
+ if (paramVal == NULL || *paramVal == NULL) {
+ rc = NS_LDAP_CONFIG;
+ *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
+ gettext("Admin bind password not configured"));
+ if (*errorp == NULL)
+ rc = NS_LDAP_MEMORY;
+ return (rc);
+ }
+ modparamVal = dvalue((char *)*paramVal);
+ (void) memset(*paramVal, 0, strlen((char *)*paramVal));
+ (void) __ns_ldap_freeParam(&paramVal);
+ if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
+ if (modparamVal != NULL)
+ free(modparamVal);
+ rc = NS_LDAP_CONFIG;
+ *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
+ gettext("bind password not valid"));
+ if (*errorp == NULL)
+ rc = NS_LDAP_MEMORY;
+ return (rc);
+ }
+
+ cred->cred.unix_cred.passwd = modparamVal;
+ return (NS_LDAP_SUCCESS);
+}
+
+boolean_t
+__ns_ldap_is_shadow_update_enabled() {
+
+ int **enable_shadow = NULL;
+
+ if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
+ (void ***)&enable_shadow, NULL) != NS_LDAP_SUCCESS) {
+ return (B_FALSE);
+ }
+ if ((enable_shadow != NULL && *enable_shadow != NULL) &&
+ (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
+ (void) __ns_ldap_freeParam((void ***)&enable_shadow);
+ return (B_TRUE);
+ }
+ if (enable_shadow != NULL)
+ (void) __ns_ldap_freeParam((void ***)&enable_shadow);
+ return (B_FALSE);
+}
+
+/*
+ * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
+ * on the LDAP server. 'service' indicates the type of database entries
+ * to modify. When the Native LDAP client is configured with 'shadow update
+ * enabled', Shadowshadow(4) entries can only be modified by privileged users.
+ * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
+ * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
+ * for performing the LDAP modify operation. ldap_cachemgr would call
+ * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
+ * to identify itself, so that admin credential would be obtained and
+ * the actual LDAP modify operation be done.
+ */
/*ARGSUSED*/
int
__ns_ldap_repAttr(
@@ -1169,6 +1254,8 @@ __ns_ldap_repAttr(
{
LDAPMod **mods;
int rc = 0;
+ boolean_t priv;
+ boolean_t shadow_update_enabled = B_FALSE;
#ifdef DEBUG
(void) fprintf(stderr, "__ns_ldap_repAttr START\n");
@@ -1176,13 +1263,59 @@ __ns_ldap_repAttr(
*errorp = NULL;
/* Sanity check */
- if ((attr == NULL) || (*attr == NULL) ||
- (dn == NULL) || (cred == NULL))
+ if (attr == NULL || *attr == NULL || dn == NULL)
+ return (NS_LDAP_INVALID_PARAM);
+
+ /* Privileged shadow modify? */
+ if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
+ strcmp(service, "shadow") == 0) {
+
+ /* Shadow update enabled ? If not, error out */
+ shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
+ if (!shadow_update_enabled) {
+ *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
+ gettext("Shadow Update is not enabled"));
+ return (NS_LDAP_CONFIG);
+ }
+
+ /* privileged shadow modify requires euid 0 or all zone privs */
+ priv = (geteuid() == 0);
+ if (!priv) {
+ priv_set_t *ps = priv_allocset(); /* caller */
+ priv_set_t *zs; /* zone */
+
+ (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)
+ return (NS_LDAP_OP_FAILED);
+
+ rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
+ return (rc);
+ }
+
+ if (cred == NULL)
return (NS_LDAP_INVALID_PARAM);
+
+ /*
+ * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
+ * ldap_cachemgr. We need to get the admin cred to do work.
+ * If the caller is not ldap_cachemgr, but use the service
+ * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
+ * as the admin cred is not available to the caller.
+ */
+ if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
+ if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
+ NS_LDAP_SUCCESS)
+ return (rc);
+ }
+
mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
- if (mods == NULL) {
+ if (mods == NULL)
return (NS_LDAP_MEMORY);
- }
rc = write_state_machine(LDAP_REQ_MODIFY,
(char *)dn, mods, cred, flags, errorp);
@@ -1191,7 +1324,6 @@ __ns_ldap_repAttr(
return (rc);
}
-
/*ARGSUSED*/
int
__ns_ldap_addEntry(
@@ -3793,3 +3925,157 @@ __s_api_append_default_basedn(
(void) __ns_ldap_freeParam(&param);
return (NS_LDAP_SUCCESS);
}
+
+/*
+ * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
+ * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
+ * The output contains a count, a list of offsets, which show where the
+ * corresponding copied attribute type and attribute value are located.
+ * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
+ * the output is the ldap_strlist_t structure with: ldap_count = 6,
+ * (buf + ldap_offsets[0]) -> "dn"
+ * (buf + ldap_offsets[1]) -> "aaaa"
+ * (buf + ldap_offsets[2]) -> "userPassword"
+ * (buf + ldap_offsets[3]) -> "bbbb"
+ * (buf + ldap_offsets[4]) -> "shadowlastchange"
+ * (buf + ldap_offsets[5]) -> "cccc"
+ * and all the string data shown above copied into the buffer after
+ * the offset array. The total length of the data will be the return
+ * value, or -1 if error.
+ */
+static int
+attr2list(const char *dn, ns_ldap_attr_t **attr,
+ char *buf, int bufsize)
+{
+ int c = 0;
+ char *ap;
+ int ao;
+ ldap_strlist_t *al = (ldap_strlist_t *)buf;
+ ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
+ ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
+
+ /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
+ if ((strlen(dn) + 2 + 1) >= bufsize)
+ return (-1);
+
+ /* count number of attributes */
+ while (*aptr++)
+ c++;
+ al->ldap_count = 2 + c * 2;
+ ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
+ al->ldap_count;
+ if (ao > bufsize)
+ return (-1);
+ al->ldap_offsets[0] = ao;
+ ap = buf + ao;
+ ao += 3;
+
+ /* copy entry DN */
+ if (ao > bufsize)
+ return (-1);
+ (void) strlcpy(ap, "dn", bufsize);
+ ap += 3;
+
+ al->ldap_offsets[1] = ao;
+ ao += strlen(dn) + 1;
+ if (ao > bufsize)
+ return (-1);
+ (void) strlcpy(ap, dn, bufsize);
+ ap = buf + ao;
+
+ aptr = attr;
+ for (c = 2; c < al->ldap_count; c++, aptr++) {
+ a = *aptr;
+ if (a->attrname == NULL || a->attrvalue == NULL ||
+ a->value_count != 1 || a->attrvalue[0] == NULL)
+ return (-1);
+ al->ldap_offsets[c] = ao;
+ ao += strlen(a->attrname) + 1;
+ if (ao > bufsize)
+ return (-1);
+ (void) strlcpy(ap, a->attrname, bufsize);
+ ap = buf + ao;
+
+ c++;
+ al->ldap_offsets[c] = ao;
+ ao += strlen(a->attrvalue[0]) + 1;
+ (void) strlcpy(ap, a->attrvalue[0], bufsize);
+ ap = buf + ao;
+ };
+
+ return (ao);
+}
+
+/*
+ * Send a modify request to the ldap_cachemgr daemon
+ * which will use the admin credential to perform the
+ * operation.
+ */
+
+static int
+send_to_cachemgr(
+ const char *dn,
+ ns_ldap_attr_t **attr,
+ ns_ldap_error_t **errorp)
+{
+ union {
+ ldap_data_t s_d;
+ char s_b[DOORBUFFERSIZE];
+ } space;
+
+ ldap_data_t *sptr;
+ int ndata;
+ int adata;
+ int len;
+ int rc;
+ char errstr[MAXERROR];
+ ldap_admin_mod_result_t *admin_result;
+
+ *errorp = NULL;
+ (void) memset(space.s_b, 0, DOORBUFFERSIZE);
+ len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
+ sizeof (space) - offsetof(ldap_return_t, ldap_u));
+ if (len <= 0)
+ return (NS_LDAP_INVALID_PARAM);
+
+ adata = sizeof (ldap_call_t) + len;
+ ndata = sizeof (space);
+ space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
+ sptr = &space.s_d;
+
+ switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
+ case NS_CACHE_SUCCESS:
+ break;
+ case NS_CACHE_NOTFOUND:
+ (void) snprintf(errstr, sizeof (errstr),
+ gettext("Door call ADMINMODIFY to "
+ "ldap_cachemgr failed - error: %d"),
+ space.s_d.ldap_ret.ldap_errno);
+ MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
+ strdup(errstr), NULL);
+ return (NS_LDAP_OP_FAILED);
+ break;
+ default:
+ return (NS_LDAP_OP_FAILED);
+ }
+
+ admin_result = &sptr->ldap_ret.ldap_u.admin_result;
+ if (admin_result->ns_err == NS_LDAP_SUCCESS)
+ rc = NS_LDAP_SUCCESS;
+ else {
+ rc = admin_result->ns_err;
+ if (admin_result->msg_size == 0)
+ *errorp = __s_api_make_error(admin_result->status,
+ NULL);
+ else
+ *errorp = __s_api_make_error(admin_result->status,
+ admin_result->msg);
+ }
+
+ /* clean up the door call */
+ if (sptr != &space.s_d) {
+ (void) munmap((char *)sptr, ndata);
+ }
+
+ return (rc);
+}