2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A/* Additional headers for addTypedEntry Conversion routines */ 2N/A * Check to see if the UPDATE_SHADOW flag is set and the 2N/A * service is one of the services that are allowed to be modified 2N/A * with the UPDATE_SHADOW privilege. 2N/A * If the rdn is a mapped attr: 2N/A * return NS_LDAP_SUCCESS and a new_dn. 2N/A * If no mapped attr is found in the rdn: 2N/A * return NS_LDAP_SUCCESS and *new_dn == NULL 2N/A * dn = cn=foo,dc=bar,dc=com 2N/A * attributeMapping: abc:cn=sn 2N/A * new_dn = sn=foo,dc=bar,dc=com 2N/A * separate dn into individual components 2N/A * "automountKey=user_01" , "automountMapName_test=auto_home", ... 2N/A /* we only check schema mapping for automount, not for auto_* */ 2N/A * The new length is *dn length + (difference between 2N/A * orig attr and mapped attr) + 1 ; 2N/A * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com 2N/A * cn=aa,automountMapName=auto_home,dc=foo,dc=com 2N/A * The following function is only used by the 2N/A * "gecos" 1 to N attribute mapping code. It expects 2N/A /* dup attribute name */ 2N/A * assume single value, 2N/A /* set pointer to data */ 2N/A * turn on the BVALUE bit to indicate 2N/A * that the length of data is supplied 2N/A /* free attribute name */ 2N/A * LDAP_MOD_BVALUES is only set by 2N/A * the "gecos" 1 to N attribute mapping 2N/A * code, and the attribute is single valued. 2N/A * only values for the "objectclass" 2N/A * were dupped using strdup. 2N/A * other attribute values were 2N/A * not dupped, but via pointer 2N/A * assignment. So here the 2N/A * values for "objectclass" 2N/A * is freed one by one, 2N/A * but the values for other 2N/A * attributes need not be freed. 2N/A * add 2 for "gecos" 1 to up to 3 attribute mapping 2N/A * add 2 for "gecos" 1 to up to 3 attribute mapping 2N/A * see if schema mapping existed for the given service 2N/A * Perform attribute mapping if necessary. 2N/A * if service == auto_xxx and 2N/A * no mapped attribute is found 2N/A * and NS_LDAP_NOMAP is not set 2N/A * then try automount's mapped attribute 2N/A * 1 to N attribute mapping is only done for "gecos", 2N/A * and only 1 to 3 mapping. 2N/A * A. attrMap=passwd:gecos=a 2N/A * 1. gecos="xx,yy,zz" -> a="xx,yy,zz" 2N/A * 2. gecos="xx,yy" -> a="xx,yy" 2N/A * 3. gecos="xx" -> a="xx" 2N/A * B. attrMap=passwd:gecos=a b 2N/A * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz" 2N/A * 5. gecos="xx,yy" -> a="xx" b="yy" 2N/A * 6. gecos="xx" -> a="xx" 2N/A * C. attrMap=passwd:gecos=a b c 2N/A * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz" 2N/A * 8. gecos="xx,yy" -> a="xx" b="yy" 2N/A * 9. gecos="xx" -> a="xx" 2N/A * This can be grouped as: 2N/A * c1 cases: 1,2,3,6,9 2N/A * if ((attrMap=passwd:gecos=a) || 2N/A * (no "," in gecos value)) 2N/A * same as other no-mapping attributes, 2N/A * no special processing needed 2N/A * if ((attrMap=passwd:gecos=a b) || 2N/A * (only one "," in gecos value)) 2N/A * notes: in case c2 and c3, ... could still contain "," 2N/A /* is there a second comma? */ 2N/A * Process case c2 or c3. 2N/A * case c2: mapped to two attributes or just 2N/A * int mod structure for the first attribute 2N/A /* don't leave a hole in mods array */ 2N/A * init mod structure for the 2nd attribute 2N/A * get pointer to data. 2N/A * Skip leading spaces. 2N/A /* get data length */ 2N/A /* don't leave a hole in mods array */ 2N/A /* done with the mapping array */ 2N/A * int mod structure for the first attribute 2N/A /* don't leave a hole in mods array */ 2N/A * init mod structure for the 2nd attribute 2N/A * get pointer to data. 2N/A * Skip leading spaces. 2N/A /* get data length */ 2N/A /* don't leave a hole in mods array */ 2N/A * init mod structure for the 3rd attribute 2N/A * get pointer to data. 2N/A * Skip leading spaces. 2N/A /* get data length */ 2N/A /* don't leave a hole in mods array */ 2N/A /* done with the mapping array */ 2N/A * Perform objectclass mapping. 2N/A * Note that the values for the "objectclass" attribute 2N/A * will be dupped using strdup. Values for other 2N/A * attributes will be referenced via pointer 2N/A * if service == auto_xxx and 2N/A * no mapped objectclass is found 2N/A * then try automount 2N/A /* assume single mapping */ 2N/A /* ASSIGN NOT COPY */ 2N/A /* count number of attributes */ 2N/A * operations to configured LDAP servers. 2N/A /* referrals returned by the LDAP operation */ 2N/A * There can be only one referral from the an LDAP write 2N/A * operation. The write state machine only allows one level 2N/A * referral. If a referral server returns a further referral 2N/A * it is ignored. The referral is stored in the referral_list 2N/A * for the state machine. The returned referral can have 2N/A * multiple references to other servers. (ref_info(s)) 2N/A * These multiple references can represent master-slave(s) or 2N/A * multi-masters configurations. These multiple references 2N/A * are tried until one is successful. 2N/A /* return the MT connection and free the conn user */ 2N/A /* see if need to follow referrals */ 2N/A /* identify self as a write user */ 2N/A * If password control attached 2N/A * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 2N/A * free the error structure (we do not need 2N/A * the password management info). 2N/A * Reset rc to NS_LDAP_SUCCESS. 2N/A /* Try the next refered server */ 2N/A * No need to deal with the error message if 2N/A * it's an empty string. 2N/A * ldap_get_lderrno does not expect 2N/A * errmsg to be freed after use, while 2N/A * ldap_parse_result below does, so set 2N/A * a flag to indicate source. 2N/A /* if no server response, set Errno */ 2N/A * need Errno, referrals, error msg, 2N/A * and the last "1" is to free 2N/A * free errmsg if it is an empty string 2N/A * If we received referral data, process 2N/A * - we are configured to follow referrals 2N/A * - and not already in referral mode (to keep 2N/A * consistency with search_state_machine() 2N/A * which follows 1 level of referrals only; 2N/A * see proc_result_referrals() and 2N/A * proc_search_references(). 2N/A /* add to referral list */ 2N/A * since we are starting over, 2N/A * discard the old error info 2N/A /* set it up to use a referral connection */ 2N/A * If an MT connection is being used, 2N/A * return it to the pool. 2N/A /* Find a referral ref that works */ 2N/A * If password control attached 2N/A * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, 2N/A * free the error structure (we do not need 2N/A * the password management info). 2N/A * Reset rc to NS_LDAP_SUCCESS. 2N/A * If current referral is not 2N/A * available for some reason, 2N/A * try next server in the ref_info list. 2N/A * Get LDAP error code from errorp. 2N/A * no more ref_info to 2N/A * free errorp before going to 2N/A * free errorp before going to W_ERROR 2N/A /* target DN may changed due to referrals */ 2N/A * map error code and error message 2N/A * to password status if necessary. 2N/A * This is to see if password updates 2N/A * failed due to password policy or 2N/A * password syntax checking. 2N/A * check if server supports 2N/A * password management 2N/A * free only if not returned by ldap_get_lderrno 2N/A " (state = %d, rc = %d)."),
2N/A * should never be here, the next line is to eliminating 2N/A /* Shadow update enabled ? If not, error out */ 2N/A /* privileged modify requires euid 0 or all zone privs */ 2N/A /* Privileged modify? */ 2N/A * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 2N/A * ldap_cachemgr. We need to get the admin cred to do work. 2N/A * If the caller is not ldap_cachemgr, but use the service 2N/A * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 2N/A * as the admin cred is not available to the caller. 2N/A /* Privileged modify? */ 2N/A * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 2N/A * ldap_cachemgr. We need to get the admin cred to do work. 2N/A * If the caller is not ldap_cachemgr, but use the service 2N/A * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 2N/A * as the admin cred is not available to the caller. 2N/A/* Retrieve the admin bind password from the configuration, if allowed. */ 2N/A * admin bind password 2N/A * Retrieve admin bind password. 2N/A * The admin bind password is available 2N/A * only in the ldap_cachemgr process as 2N/A * they are not exposed outside of that 2N/A * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored 2N/A * on the LDAP server. 'service' indicates the type of database entries 2N/A * to modify. When the Native LDAP client is configured with 'shadow update 2N/A * enabled', RBAC related entries can only be modified by privileged users. 2N/A * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is 2N/A * for such an update, which would be forwarded to ldap_cachemgr 2N/A * for performing the LDAP modify operation. ldap_cachemgr would call 2N/A * this function again and use the special service NS_ADMIN_SHADOW_UPDATE 2N/A * to identify itself, so that admin credential would be obtained and 2N/A * the actual LDAP modify operation be done. 2N/A /* Privileged modify? */ 2N/A * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 2N/A * ldap_cachemgr. We need to get the admin cred to do work. 2N/A * If the caller is not ldap_cachemgr, but use the service 2N/A * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 2N/A * as the admin cred is not available to the caller. 2N/A /* Privileged modify? */ 2N/A * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 2N/A * ldap_cachemgr. We need to get the admin cred to do work. 2N/A * If the caller is not ldap_cachemgr, but use the service 2N/A * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 2N/A * as the admin cred is not available to the caller. 2N/A /* Construct array of LDAPMod representing attributes of new entry. */ 2N/A /* Privileged modify? */ 2N/A * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be 2N/A * ldap_cachemgr. We need to get the admin cred to do work. 2N/A * If the caller is not ldap_cachemgr, but use the service 2N/A * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail, 2N/A * as the admin cred is not available to the caller. 2N/A * Add Typed Entry Helper routines 2N/A * Add Typed Entry Conversion routines 2N/A for (j = 0; j < i; j++) {
2N/A for (i = 0; i < j; i++)
2N/A /* allocate attributes, +1 for objectclass, +1 for NULL terminator */ 2N/A * Conversion: passwd 2N/A * Input format: struct passwd 2N/A * Exported objectclass: posixAccount 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * escape_str function escapes special characters in str and 2N/A * copies to escstr string. 2N/A * return 0 for successful 2N/A * Conversion: project 2N/A * Input format: struct project 2N/A * Exported objectclass: SolarisProject 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * ibuf is 11 chars big, which should be enough for string 2N/A * representation of 32bit number + nul-car 2N/A * Conversion: shadow 2N/A * Input format: struct shadow 2N/A * Exported objectclass: shadowAccount 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * Input format: struct group 2N/A * Exported objectclass: posixGroup 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++) {
2N/A for (k = 0; k < j; k++)
2N/A for (j = 0; j < i; j++) {
2N/A * Input format: struct hostent 2N/A * Exported objectclass: ipHost 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * If there is a description, 'i' will contain 2N/A * the index of the description in the aliases list 2N/A for (i = 0; *
lm && (*
lm)[0] !=
'#'; i++,
lm++)
2N/A for (j = 0; j < i; j++)
2N/A for (j = 0; j < i; j++) {
2N/A for (k = 0; k < j; k++)
2N/A for (j = 0; j < i; j++) {
2N/A * Input format: struct rpcent 2N/A * Exported objectclass: oncRpc 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: protocols 2N/A * Input format: struct protoent 2N/A * Exported objectclass: ipProtocol 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: services 2N/A * Input format: struct servent 2N/A * Exported objectclass: ipService 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A * Escape special characters in service name. 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: networks 2N/A * Input format: struct netent 2N/A * Exported objectclass: ipNetwork 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: netmasks 2N/A * Input format: struct _ns_netmasks 2N/A * Exported objectclass: ipNetwork 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * Conversion: netgroups 2N/A * Input format: struct _ns_netgroups 2N/A * Exported objectclass: nisNetgroup 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A for (j = 0; j < i; j++)
2N/A * Conversion: bootparams 2N/A * Input format: struct _ns_bootp 2N/A * Exported objectclass: bootableDevice, device 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: ethers 2N/A * Input format: struct _ns_ethers 2N/A * Exported objectclass: ieee802Device, device 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * This function is used when processing an ethers (objectclass: ieee802Device) 2N/A * or a bootparams (objectclass: bootableDevice) entry, and the entry is 2N/A * already found in LDAP. Since both ethers and bootparams share the same 2N/A * LDAP container, we want to check that the entry found in LDAP is: 2N/A * - either the same entry (same cn, same objectclass): we don't do anything 2N/A * - or an entry which does not have the objectclass we are interesting in: 2N/A * in this case, we modify the existing entry by adding the relevant 2N/A * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s) 2N/A * from the attribute list previously computing by the relevant conversion 2N/A * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams() 2N/A * we know that there is only 1 more attribute today to add (macAddress 2N/A "(&(objectClass=ieee802Device)(%s))",
rdn);
2N/A "(&(objectClass=bootableDevice)(%s))",
rdn);
2N/A * entry already exists for this service 2N/A * return NS_LDAP_INTERNAL and do not modify the incoming errorp 2N/A * entry not found with the given objectclasss but entry exists 2N/A * hence add the relevant attribute (macAddress or bootparams). 2N/A /* aptr2 needed here to avoid lint warning */ 2N/A "objectclass") != 0)) {
2N/A /* we haven't found all expected attributes */ 2N/A /* clean errorp first */ 2N/A * unexpected error happenned 2N/A * returning relevant error 2N/A * Conversion: publickey 2N/A * Input format: struct _ns_pubkey 2N/A * Exported objectclass: NisKeyObject 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A * Conversion: aliases 2N/A * Input format: struct _ns_alias 2N/A * Exported objectclass: mailGroup 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A /* Error check the data and add the attributes */ 2N/A for (j = 0; j < i; j++)
2N/A * Conversion: automount 2N/A * Input format: struct _ns_automount 2N/A * Exported objectclass: automount 2N/A /* routine specific */ 2N/A /* determine profile version number */ 2N/A /* use old schema for version 1 profiles */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * even for version 2, if automount is mapped to nisObject we 2N/A * still need 'nisMapName' attribute 2N/A * Conversion: auth_attr 2N/A * Input format: authstr_t 2N/A * Exported objectclass: SolarisAuthAttr 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * Conversion: exec_attr 2N/A * Input format: execstr_t 2N/A * Exported objectclass: SolarisExecAttr 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A * Escape special characters in ProfileID. 2N/A /* Create an appropriate rdn */ 2N/A "+SolarisProfileType=%s+SolarisProfileId=%s",
2N/A * Conversion: prof_attr 2N/A * Input format: profstr_t 2N/A * Exported objectclass: SolarisProfAttr 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * Conversion: user_attr 2N/A * Input format: userstr_t 2N/A * Exported objectclass: SolarisUserAttr 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * SolarisUserAttr has no uid attribute 2N/A * Conversion: audit_user 2N/A * Input format: au_user_str_t 2N/A * Exported objectclass: SolarisAuditUser 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * Solaris AuditUser has no uid attribute 2N/A * Conversion: tnrhtp 2N/A * Input format: tsol_tpstr_t 2N/A * Exported objectclass: ipTnetTemplate 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A * Escape special characters in Template name. 2N/A /* Create an appropriate rdn */ 2N/A * Conversion: tnrhdb 2N/A * Input format: tsol_rhstr_t 2N/A * Exported objectclass: ipTnetHost 2N/A /* routine specific */ 2N/A /* Convert the structure */ 2N/A /* Create an appropriate rdn */ 2N/A * Add Typed Entry Conversion data structures 2N/A#
define AE 1 /* alway add entries */ 2N/A * Add Typed Entry Routine 2N/A /* Or, check if the servicetype is auto_ */ 2N/A /* Convert the data */ 2N/A /* Create the Full DN */ 2N/A /* Check to see if the entry exists already */ 2N/A /* May need to delete or update first */ 2N/A /* Modify the entry */ 2N/A * To add a shadow-like entry, the addTypedEntry function 2N/A * would call __ns_ldap_repAttr first, and if server says 2N/A * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry. 2N/A * This is to allow a netmask entry to be added even if the 2N/A * base network entry is not in the directory. It would work 2N/A * because the difference between the schema for the network 2N/A * and netmask data contains only MAY attributes. 2N/A * But for shadow data, the attributes do not have MUST 2N/A * attributes the base entry needs, so if the __ns_ldap_addEntry 2N/A * is executed, it would fail. The real reason, however, is that 2N/A * the base entry did not exist. So returning 2N/A * LDAP_OBJECT_CLASS_VIOLATION would just confused. 2N/A /* Free up entry created by conversion routine */ 2N/A * Append the default base dn to the dn 2N/A * when it ends with ','. 2N/A * SSD = service:ou=foo, 2N/A * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an 2N/A * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr. 2N/A * The output contains a count, a list of offsets, which show where the 2N/A * corresponding copied attribute type and attribute value are located. 2N/A * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc, 2N/A * the output is the ldap_strlist_t structure with: ldap_count = 6, 2N/A * (buf + ldap_offsets[0]) -> "dn" 2N/A * (buf + ldap_offsets[1]) -> "aaaa" 2N/A * (buf + ldap_offsets[2]) -> "userPassword" 2N/A * (buf + ldap_offsets[3]) -> "bbbb" 2N/A * (buf + ldap_offsets[4]) -> "shadowlastchange" 2N/A * (buf + ldap_offsets[5]) -> "cccc" 2N/A * and all the string data shown above copied into the buffer after 2N/A * the offset array. The total length of the data will be the return 2N/A * value, or -1 if error. 2N/A /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */ 2N/A /* count number of attributes */ 2N/A * Some attributes have multiple values (ex: objectClass) 2N/A * For some operations we do not send ObjectClass attributes 2N/A * because the server will not let it be modified. 2N/A * Don't pass objectClass attributes when modifying 2N/A * an existing entry. 2N/A * For each value, write the attrname + attrvalue 2N/A * so they can be parsed later by the cachemgr. 2N/A * Send a modify request to the ldap_cachemgr daemon 2N/A * which will use the admin credential to perform the 2N/A "ldap_cachemgr failed - error: %d"),
2N/A /* clean up the door call */