| /* |
| * 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 |
| * or http://www.opensolaris.org/os/licensing. |
| * 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 2006 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> |
| #include <libintl.h> |
| |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <strings.h> |
| #include <lber.h> |
| #include <ldap.h> |
| #include <syslog.h> |
| |
| #include "ns_sldap.h" |
| #include "ns_internal.h" |
| |
| /* Additional headers for addTypedEntry Conversion routines */ |
| #include <pwd.h> |
| #include <shadow.h> |
| #include <grp.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <netdb.h> |
| #include <rpc/rpcent.h> |
| #include <auth_attr.h> |
| #include <exec_attr.h> |
| #include <prof_attr.h> |
| #include <user_attr.h> |
| #include <bsm/libbsm.h> |
| #include <sys/tsol/tndb.h> |
| #include <tsol/label.h> |
| |
| |
| /* |
| * If the rdn is a mapped attr: |
| * return NS_LDAP_SUCCESS and a new_dn. |
| * If no mapped attr is found in the rdn: |
| * return NS_LDAP_SUCCESS and *new_dn == NULL |
| * For example: |
| * service = abc |
| * dn = cn=foo,dc=bar,dc=com |
| * attributeMapping: abc:cn=sn |
| * Then: |
| * new_dn = sn=foo,dc=bar,dc=com |
| * |
| */ |
| static int |
| replace_mapped_attr_in_dn( |
| const char *service, const char *dn, char **new_dn) |
| { |
| char **mappedattr; |
| char **dnArray = NULL; |
| char *rservice; |
| char *cur = NULL; |
| int len = 0, orig_len = 0, mapped_len = 0; |
| int dn_len = 0; |
| |
| *new_dn = NULL; |
| |
| /* |
| * seperate dn into individual componets |
| * e.g. |
| * "automountKey=user_01" , "automountMapName_test=auto_home", ... |
| */ |
| dnArray = ldap_explode_dn(dn, 0); |
| if (!dnArray || !*dnArray) |
| return (NS_LDAP_INVALID_PARAM); |
| |
| cur = strchr(dnArray[0], '='); |
| if (!cur) { |
| __s_api_free2dArray(dnArray); |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| *cur = '\0'; |
| |
| /* we only check schema mapping for automount, not for auto_* */ |
| if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT, |
| sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) |
| rservice = "automount"; |
| else |
| rservice = (char *)service; |
| |
| mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]); |
| if (!mappedattr || !mappedattr[0]) { |
| __s_api_free2dArray(dnArray); |
| if (mappedattr) |
| __s_api_free2dArray(mappedattr); |
| return (NS_LDAP_SUCCESS); |
| } |
| orig_len = strlen(dnArray[0]); |
| |
| /* |
| * The new length is *dn length + (difference between |
| * orig attr and mapped attr) + 1 ; |
| * e.g. |
| * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com |
| * ==> |
| * cn=aa,automountMapName=auto_home,dc=foo,dc=com |
| */ |
| mapped_len = strlen(mappedattr[0]); |
| dn_len = strlen(dn); |
| len = dn_len - orig_len + mapped_len + 1; |
| *new_dn = (char *)calloc(1, len); |
| if (*new_dn == NULL) { |
| __s_api_free2dArray(dnArray); |
| __s_api_free2dArray(mappedattr); |
| return (NS_LDAP_MEMORY); |
| } |
| |
| (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1); |
| __s_api_free2dArray(dnArray); |
| __s_api_free2dArray(mappedattr); |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| |
| /* |
| * The following function is only used by the |
| * "gecos" 1 to N attribute mapping code. It expects |
| * and handle only one data/length pair. |
| */ |
| static int |
| init_bval_mod( |
| LDAPMod *mod, |
| int mop, |
| char *mtype, |
| char *mvptr, |
| int mvlen) |
| { |
| |
| struct berval **bmodval; |
| |
| /* dup attribute name */ |
| mod->mod_type = strdup(mtype); |
| if (mod->mod_type == NULL) |
| return (-1); |
| |
| /* |
| * assume single value, |
| * since only one value/length pair passed in |
| */ |
| bmodval = (struct berval **)calloc(2, |
| sizeof (struct berval *)); |
| if (bmodval == NULL) { |
| free(mod->mod_type); |
| mod->mod_type = NULL; |
| return (-1); |
| } |
| bmodval[0] = (struct berval *)calloc(1, |
| sizeof (struct berval)); |
| if (bmodval[0] == NULL) { |
| free(mod->mod_type); |
| mod->mod_type = NULL; |
| free(bmodval); |
| return (-1); |
| } |
| |
| /* set pointer to data */ |
| bmodval[0]->bv_val = mvptr; |
| |
| /* set length */ |
| bmodval[0]->bv_len = mvlen; |
| |
| /* |
| * turn on the BVALUE bit to indicate |
| * that the length of data is supplied |
| */ |
| mod->mod_op = mop | LDAP_MOD_BVALUES; |
| |
| mod->mod_bvalues = bmodval; |
| |
| return (0); |
| } |
| |
| static void |
| freeModList(LDAPMod **mods) |
| { |
| int i, j; |
| int name_is_oc; |
| |
| if (mods == NULL) |
| return; |
| |
| for (i = 0; mods[i]; i++) { |
| |
| /* free attribute name */ |
| name_is_oc = FALSE; |
| if (mods[i]->mod_type) { |
| if (strcasecmp(mods[i]->mod_type, |
| "objectclass") == 0) |
| name_is_oc = TRUE; |
| free(mods[i]->mod_type); |
| } |
| |
| if (mods[i]->mod_bvalues == NULL) |
| continue; |
| /* |
| * LDAP_MOD_BVALUES is only set by |
| * the "gecos" 1 to N attribute mapping |
| * code, and the attribute is single valued. |
| */ |
| if (mods[i]->mod_op & LDAP_MOD_BVALUES) { |
| if (mods[i]->mod_bvalues[0]) |
| free(mods[i]->mod_bvalues[0]); |
| } else { |
| if (name_is_oc) { |
| /* |
| * only values for the "objectclass" |
| * were dupped using strdup. |
| * other attribute values were |
| * not dupped, but via pointer |
| * assignment. So here the |
| * values for "objectclass" |
| * is freed one by one, |
| * but the values for other |
| * attributes need not be freed. |
| */ |
| for (j = 0; mods[i]->mod_values[j]; j++) |
| free(mods[i]->mod_values[j]); |
| } |
| |
| } |
| free(mods[i]->mod_bvalues); |
| } |
| |
| /* modlist */ |
| free((char *)(mods[0])); |
| free(mods); |
| } |
| |
| static LDAPMod ** |
| __s_api_makeModListCount( |
| const char *service, |
| const ns_ldap_attr_t * const *attr, |
| const int mod_op, |
| const int count, |
| const int flags) |
| { |
| LDAPMod **mods, *modlist; |
| char **modval; |
| char **mapping; |
| int i; |
| int j; |
| int k, rc, vlen; |
| char *c, *comma1 = NULL, *comma2 = NULL; |
| int schema_mapping_existed = FALSE; |
| int auto_service = FALSE; |
| |
| |
| /* |
| * add 2 for "gecos" 1 to up to 3 attribute mapping |
| */ |
| mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *)); |
| if (mods == NULL) { |
| return (NULL); |
| } |
| /* |
| * add 2 for "gecos" 1 to up to 3 attribute mapping |
| */ |
| modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod)); |
| if (modlist == NULL) { |
| free(mods); |
| return (NULL); |
| } |
| |
| if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT, |
| sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) |
| auto_service = TRUE; |
| |
| /* |
| * see if schema mapping existed for the given service |
| */ |
| mapping = __ns_ldap_getOrigAttribute(service, |
| NS_HASH_SCHEMA_MAPPING_EXISTED); |
| if (mapping) { |
| schema_mapping_existed = TRUE; |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| } |
| |
| for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) { |
| mods[i] = &modlist[i]; |
| mods[i]->mod_op = mod_op; |
| /* |
| * Perform attribute mapping if necessary. |
| */ |
| if (schema_mapping_existed && |
| (flags & NS_LDAP_NOMAP) == 0) { |
| mapping = __ns_ldap_getMappedAttributes(service, |
| attr[k]->attrname); |
| } else |
| mapping = NULL; |
| |
| if (mapping == NULL && auto_service && |
| (flags & NS_LDAP_NOMAP) == 0) { |
| /* |
| * if service == auto_xxx and |
| * no mapped attribute is found |
| * and NS_LDAP_NOMAP is not set |
| * then try automount's mapped attribute |
| */ |
| mapping = __ns_ldap_getMappedAttributes("automount", |
| attr[k]->attrname); |
| } |
| |
| if (mapping == NULL) { |
| mods[i]->mod_type = strdup(attr[k]->attrname); |
| if (mods[i]->mod_type == NULL) { |
| goto free_memory; |
| } |
| } else { |
| /* |
| * 1 to N attribute mapping is only done for "gecos", |
| * and only 1 to 3 mapping. |
| * nine cases here: |
| * |
| * A. attrMap=passwd:gecos=a |
| * 1. gecos="xx,yy,zz" -> a="xx,yy,zz" |
| * 2. gecos="xx,yy" -> a="xx,yy" |
| * 3. gecos="xx" -> a="xx" |
| * |
| * B. attrMap=passwd:gecos=a b |
| * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz" |
| * 5. gecos="xx,yy" -> a="xx" b="yy" |
| * 6. gecos="xx" -> a="xx" |
| * |
| * C. attrMap=passwd:gecos=a b c |
| * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz" |
| * 8. gecos="xx,yy" -> a="xx" b="yy" |
| * 9. gecos="xx" -> a="xx" |
| * |
| * This can be grouped as: |
| * |
| * c1 cases: 1,2,3,6,9 |
| * if ((attrMap=passwd:gecos=a) || |
| * (no "," in gecos value)) |
| * same as other no-mapping attributes, |
| * no special processing needed |
| * else |
| * |
| * c2 cases: 4,5,8 |
| * if ((attrMap=passwd:gecos=a b) || |
| * (only one "," in gecos value)) |
| * a=xx b=yy[,...] |
| * else |
| * |
| * c3 case: 7 |
| * a=xx b=yy c=... |
| * |
| * notes: in case c2 and c3, ... could still contain "," |
| */ |
| if (strcasecmp(service, "passwd") == 0 && |
| strcasecmp(attr[k]->attrname, "gecos") == 0 && |
| mapping[1] && attr[k]->attrvalue[0] && |
| (comma1 = strchr(attr[k]->attrvalue[0], |
| COMMATOK)) != NULL) { |
| |
| /* is there a second comma? */ |
| if (*(comma1 + 1) != '\0') |
| comma2 = strchr(comma1 + 1, COMMATOK); |
| |
| /* |
| * Process case c2 or c3. |
| * case c2: mapped to two attributes or just |
| * one comma |
| */ |
| if (mapping[2] == NULL || |
| comma2 == NULL) { |
| /* case c2 */ |
| |
| /* |
| * int mod structure for the first attribute |
| */ |
| vlen = comma1 - attr[k]->attrvalue[0]; |
| c = attr[k]->attrvalue[0]; |
| |
| if (vlen > 0 && c) { |
| rc = init_bval_mod(mods[i], mod_op, |
| mapping[0], c, vlen); |
| if (rc != 0) |
| goto free_memory; |
| } else { |
| /* don't leave a hole in mods array */ |
| mods[i] = NULL; |
| i--; |
| } |
| |
| |
| /* |
| * init mod structure for the 2nd attribute |
| */ |
| if (*(comma1 + 1) == '\0') { |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| continue; |
| } |
| |
| i++; |
| mods[i] = &modlist[i]; |
| |
| /* |
| * get pointer to data. |
| * Skip leading spaces. |
| */ |
| for (c = comma1 + 1; *c == SPACETOK; c++); |
| |
| /* get data length */ |
| vlen = strlen(attr[k]->attrvalue[0]) - |
| (c - attr[k]->attrvalue[0]); |
| |
| if (vlen > 0 && c) { |
| rc = init_bval_mod(mods[i], mod_op, |
| mapping[1], c, vlen); |
| if (rc != 0) |
| goto free_memory; |
| } else { |
| /* don't leave a hole in mods array */ |
| mods[i] = NULL; |
| i--; |
| } |
| |
| /* done with the mapping array */ |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| |
| continue; |
| } else { |
| /* case c3 */ |
| |
| /* |
| * int mod structure for the first attribute |
| */ |
| vlen = comma1 - attr[k]->attrvalue[0]; |
| c = attr[k]->attrvalue[0]; |
| |
| if (vlen > 0 && c) { |
| rc = init_bval_mod(mods[i], mod_op, |
| mapping[0], c, vlen); |
| if (rc != 0) |
| goto free_memory; |
| } else { |
| /* don't leave a hole in mods array */ |
| mods[i] = NULL; |
| i--; |
| } |
| |
| /* |
| * init mod structure for the 2nd attribute |
| */ |
| i++; |
| mods[i] = &modlist[i]; |
| |
| /* |
| * get pointer to data. |
| * Skip leading spaces. |
| */ |
| for (c = comma1 + 1; *c == SPACETOK; c++); |
| |
| /* get data length */ |
| vlen = comma2 - c; |
| |
| if (vlen > 0 && c) { |
| rc = init_bval_mod(mods[i], mod_op, |
| mapping[1], c, vlen); |
| if (rc != 0) |
| goto free_memory; |
| } else { |
| /* don't leave a hole in mods array */ |
| mods[i] = NULL; |
| i--; |
| } |
| |
| /* |
| * init mod structure for the 3rd attribute |
| */ |
| if (*(comma2 + 1) == '\0') { |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| continue; |
| } |
| |
| i++; |
| mods[i] = &modlist[i]; |
| /* |
| * get pointer to data. |
| * Skip leading spaces. |
| */ |
| for (c = comma2 + 1; *c == SPACETOK; c++); |
| |
| /* get data length */ |
| vlen = strlen(attr[k]->attrvalue[0]) - |
| (c - attr[k]->attrvalue[0]); |
| |
| if (vlen > 0 && c) { |
| rc = init_bval_mod(mods[i], mod_op, |
| mapping[2], c, vlen); |
| if (rc != 0) |
| goto free_memory; |
| } else { |
| /* don't leave a hole in mods array */ |
| mods[i] = NULL; |
| i--; |
| } |
| |
| /* done with the mapping array */ |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| |
| continue; |
| } |
| } |
| |
| /* case c1 */ |
| mods[i]->mod_type = strdup(mapping[0]); |
| if (mods[i]->mod_type == NULL) { |
| goto free_memory; |
| } |
| __s_api_free2dArray(mapping); |
| mapping = NULL; |
| } |
| |
| modval = (char **)calloc(attr[k]->value_count+1, |
| sizeof (char *)); |
| if (modval == NULL) |
| goto free_memory; |
| /* |
| * Perform objectclass mapping. |
| * Note that the values for the "objectclass" attribute |
| * will be dupped using strdup. Values for other |
| * attributes will be referenced via pointer |
| * assignments. |
| */ |
| if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) { |
| for (j = 0; j < attr[k]->value_count; j++) { |
| if (schema_mapping_existed && |
| (flags & NS_LDAP_NOMAP) == 0) |
| mapping = |
| __ns_ldap_getMappedObjectClass( |
| service, attr[k]->attrvalue[j]); |
| else |
| mapping = NULL; |
| |
| if (mapping == NULL && auto_service && |
| (flags & NS_LDAP_NOMAP) == 0) |
| /* |
| * if service == auto_xxx and |
| * no mapped objectclass is found |
| * then try automount |
| */ |
| mapping = |
| __ns_ldap_getMappedObjectClass( |
| "automount", attr[k]->attrvalue[j]); |
| |
| if (mapping && mapping[0]) { |
| /* assume single mapping */ |
| modval[j] = strdup(mapping[0]); |
| } else { |
| modval[j] = strdup(attr[k]-> |
| attrvalue[j]); |
| } |
| if (modval[j] == NULL) |
| goto free_memory; |
| } |
| } else { |
| for (j = 0; j < attr[k]->value_count; j++) { |
| /* ASSIGN NOT COPY */ |
| modval[j] = attr[k]->attrvalue[j]; |
| } |
| } |
| mods[i]->mod_values = modval; |
| } |
| |
| return (mods); |
| |
| free_memory: |
| freeModList(mods); |
| if (mapping) |
| __s_api_free2dArray(mapping); |
| |
| return (NULL); |
| |
| } |
| |
| static LDAPMod ** |
| __s_api_makeModList( |
| const char *service, |
| const ns_ldap_attr_t * const *attr, |
| const int mod_op, |
| const int flags) |
| { |
| ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr; |
| int count = 0; |
| |
| if (aptr == NULL) |
| return (NULL); |
| |
| /* count number of attributes */ |
| while (*aptr++) |
| count++; |
| |
| return (__s_api_makeModListCount(service, attr, mod_op, count, flags)); |
| } |
| |
| static void |
| __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn) |
| { |
| if (*entry != NULL) { |
| __ns_ldap_freeEntry(*entry); |
| *entry = NULL; |
| } |
| if (*rdn != NULL) { |
| free(*rdn); |
| *rdn = NULL; |
| } |
| } |
| |
| /* |
| * This state machine performs one or more LDAP add/delete/modify |
| * operations to configured LDAP servers. |
| */ |
| static int |
| write_state_machine( |
| int ldap_op, |
| char *dn, |
| LDAPMod **mods, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| ConnectionID connectionId = -1; |
| Connection *conp = NULL; |
| LDAPMessage *res; |
| char *target_dn = NULL; |
| char errstr[MAXERROR]; |
| int rc = NS_LDAP_SUCCESS; |
| int return_rc = NS_LDAP_SUCCESS; |
| int followRef = FALSE; |
| int target_dn_allocated = FALSE; |
| int len; |
| int msgid; |
| int Errno; |
| int always = 1; |
| char *err, *errmsg = NULL; |
| /* referrals returned by the LDAP operation */ |
| char **referrals = NULL; |
| /* |
| * list of referrals used by the state machine, built from |
| * the referrals variable above |
| */ |
| ns_referral_info_t *ref_list = NULL; |
| /* current referral */ |
| ns_referral_info_t *current_ref = NULL; |
| ns_write_state_t state = W_INIT, new_state, err_state = W_INIT; |
| int do_not_fail_if_new_pwd_reqd = 0; |
| ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD; |
| int passwd_mgmt = 0; |
| int i = 0; |
| int ldap_error; |
| int nopasswd_acct_mgmt = 0; |
| |
| while (always) { |
| switch (state) { |
| case W_EXIT: |
| if (connectionId > -1) |
| DropConnection(connectionId, 0); |
| if (ref_list) |
| __s_api_deleteRefInfo(ref_list); |
| if (target_dn && target_dn_allocated) |
| free(target_dn); |
| return (return_rc); |
| case W_INIT: |
| /* see if need to follow referrals */ |
| rc = __s_api_toFollowReferrals(flags, |
| &followRef, errorp); |
| if (rc != NS_LDAP_SUCCESS) { |
| return_rc = rc; |
| new_state = W_ERROR; |
| break; |
| } |
| len = strlen(dn); |
| if (dn[len-1] == COMMATOK) |
| rc = __s_api_append_default_basedn( |
| dn, &target_dn, |
| &target_dn_allocated, |
| errorp); |
| else |
| target_dn = dn; |
| if (rc != NS_LDAP_SUCCESS) { |
| return_rc = rc; |
| new_state = W_ERROR; |
| } |
| else |
| new_state = GET_CONNECTION; |
| break; |
| case GET_CONNECTION: |
| rc = __s_api_getConnection(NULL, |
| flags, |
| cred, |
| &connectionId, |
| &conp, |
| errorp, |
| do_not_fail_if_new_pwd_reqd, |
| nopasswd_acct_mgmt); |
| |
| /* |
| * If password control attached |
| * in *errorp, |
| * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, |
| * free the error structure (we do not need |
| * the password management info). |
| * Reset rc to NS_LDAP_SUCCESS. |
| */ |
| if (rc == NS_LDAP_SUCCESS_WITH_INFO) { |
| (void) __ns_ldap_freeError( |
| errorp); |
| *errorp = NULL; |
| rc = NS_LDAP_SUCCESS; |
| } |
| |
| if (rc != NS_LDAP_SUCCESS) { |
| return_rc = rc; |
| new_state = W_ERROR; |
| break; |
| } |
| if (followRef) |
| new_state = SELECT_OPERATION_ASYNC; |
| else |
| new_state = SELECT_OPERATION_SYNC; |
| break; |
| case SELECT_OPERATION_SYNC: |
| if (ldap_op == LDAP_REQ_ADD) |
| new_state = DO_ADD_SYNC; |
| else if (ldap_op == LDAP_REQ_DELETE) |
| new_state = DO_DELETE_SYNC; |
| else if (ldap_op == LDAP_REQ_MODIFY) |
| new_state = DO_MODIFY_SYNC; |
| break; |
| case SELECT_OPERATION_ASYNC: |
| if (ldap_op == LDAP_REQ_ADD) |
| new_state = DO_ADD_ASYNC; |
| else if (ldap_op == LDAP_REQ_DELETE) |
| new_state = DO_DELETE_ASYNC; |
| else if (ldap_op == LDAP_REQ_MODIFY) |
| new_state = DO_MODIFY_ASYNC; |
| break; |
| case DO_ADD_SYNC: |
| rc = ldap_add_ext_s(conp->ld, target_dn, |
| mods, NULL, NULL); |
| new_state = GET_RESULT_SYNC; |
| break; |
| case DO_DELETE_SYNC: |
| rc = ldap_delete_ext_s(conp->ld, target_dn, |
| NULL, NULL); |
| new_state = GET_RESULT_SYNC; |
| break; |
| case DO_MODIFY_SYNC: |
| rc = ldap_modify_ext_s(conp->ld, target_dn, |
| mods, NULL, NULL); |
| new_state = GET_RESULT_SYNC; |
| break; |
| case DO_ADD_ASYNC: |
| rc = ldap_add_ext(conp->ld, target_dn, |
| mods, NULL, NULL, &msgid); |
| new_state = GET_RESULT_ASYNC; |
| break; |
| case DO_DELETE_ASYNC: |
| rc = ldap_delete_ext(conp->ld, target_dn, |
| NULL, NULL, &msgid); |
| new_state = GET_RESULT_ASYNC; |
| break; |
| case DO_MODIFY_ASYNC: |
| rc = ldap_modify_ext(conp->ld, target_dn, |
| mods, NULL, NULL, &msgid); |
| new_state = GET_RESULT_ASYNC; |
| break; |
| case GET_RESULT_SYNC: |
| if (rc != LDAP_SUCCESS) { |
| Errno = rc; |
| (void) ldap_get_lderrno(conp->ld, |
| NULL, &errmsg); |
| /* |
| * free errmsg if it is an empty string |
| */ |
| if (errmsg && *errmsg == '\0') { |
| ldap_memfree(errmsg); |
| errmsg = NULL; |
| } |
| new_state = W_LDAP_ERROR; |
| } else { |
| return_rc = NS_LDAP_SUCCESS; |
| new_state = W_EXIT; |
| } |
| break; |
| case GET_RESULT_ASYNC: |
| rc = ldap_result(conp->ld, msgid, 1, |
| (struct timeval *)NULL, &res); |
| /* if no server response, set Errno */ |
| if (rc == -1) { |
| (void) ldap_get_option(conp->ld, |
| LDAP_OPT_ERROR_NUMBER, &Errno); |
| new_state = W_LDAP_ERROR; |
| break; |
| } |
| if (rc == LDAP_RES_ADD || |
| rc == LDAP_RES_MODIFY || |
| rc == LDAP_RES_DELETE) { |
| new_state = PARSE_RESULT; |
| break; |
| } else { |
| return_rc = rc; |
| new_state = W_ERROR; |
| } |
| break; |
| case PARSE_RESULT: |
| /* |
| * need Errno, referrals, error msg, |
| * and the last "1" is to free |
| * the result (res) |
| */ |
| rc = ldap_parse_result(conp->ld, |
| res, &Errno, |
| NULL, &errmsg, |
| &referrals, NULL, 1); |
| /* |
| * free errmsg if it is an empty string |
| */ |
| if (errmsg && *errmsg == '\0') { |
| ldap_memfree(errmsg); |
| errmsg = NULL; |
| } |
| /* |
| * If we received referral data, process |
| * it if: |
| * - we are configured to follow referrals |
| * - and not already in referral mode (to keep |
| * consistency with search_state_machine() |
| * which follows 1 level of referrals only; |
| * see proc_result_referrals() and |
| * proc_search_references(). |
| */ |
| if (Errno == LDAP_REFERRAL && followRef && !ref_list) { |
| for (i = 0; referrals[i] != NULL; i++) { |
| /* add to referral list */ |
| rc = __s_api_addRefInfo(&ref_list, |
| referrals[i], |
| NULL, NULL, NULL, |
| conp->ld); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_api_deleteRefInfo(ref_list); |
| ref_list = NULL; |
| break; |
| } |
| } |
| ldap_value_free(referrals); |
| if (ref_list == NULL) { |
| if (rc != NS_LDAP_MEMORY) |
| rc = NS_LDAP_INTERNAL; |
| return_rc = rc; |
| new_state = W_ERROR; |
| } else { |
| new_state = GET_REFERRAL_CONNECTION; |
| current_ref = ref_list; |
| } |
| if (errmsg) { |
| ldap_memfree(errmsg); |
| errmsg = NULL; |
| } |
| break; |
| } |
| if (Errno != LDAP_SUCCESS) { |
| new_state = W_LDAP_ERROR; |
| } else { |
| return_rc = NS_LDAP_SUCCESS; |
| new_state = W_EXIT; |
| } |
| break; |
| case GET_REFERRAL_CONNECTION: |
| /* |
| * since we are starting over, |
| * discard the old error info |
| */ |
| return_rc = NS_LDAP_SUCCESS; |
| if (*errorp) |
| (void) __ns_ldap_freeError(errorp); |
| if (connectionId > -1) |
| DropConnection(connectionId, 0); |
| rc = __s_api_getConnection(current_ref->refHost, |
| 0, |
| cred, |
| &connectionId, |
| &conp, |
| errorp, |
| do_not_fail_if_new_pwd_reqd, |
| nopasswd_acct_mgmt); |
| |
| /* |
| * If password control attached |
| * in errorp, |
| * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO, |
| * free the error structure (we do not need |
| * the password management info). |
| * Reset rc to NS_LDAP_SUCCESS. |
| */ |
| if (rc == NS_LDAP_SUCCESS_WITH_INFO) { |
| (void) __ns_ldap_freeError( |
| errorp); |
| *errorp = NULL; |
| rc = NS_LDAP_SUCCESS; |
| } |
| |
| if (rc != NS_LDAP_SUCCESS) { |
| return_rc = rc; |
| /* |
| * If current referral is not |
| * available for some reason, |
| * try next referral in the list. |
| * Get LDAP error code from errorp. |
| */ |
| if (*errorp != NULL) { |
| ldap_error = (*errorp)->status; |
| if (ldap_error == LDAP_BUSY || |
| ldap_error == LDAP_UNAVAILABLE || |
| ldap_error == |
| LDAP_UNWILLING_TO_PERFORM || |
| ldap_error == LDAP_CONNECT_ERROR || |
| ldap_error == LDAP_SERVER_DOWN) { |
| current_ref = current_ref->next; |
| if (current_ref == NULL) { |
| /* no more referral */ |
| /* to follow */ |
| new_state = W_ERROR; |
| } else { |
| new_state = |
| GET_REFERRAL_CONNECTION; |
| } |
| /* |
| * free errorp before going to |
| * next referral |
| */ |
| (void) __ns_ldap_freeError( |
| errorp); |
| *errorp = NULL; |
| break; |
| } |
| /* |
| * free errorp before going to W_ERROR |
| */ |
| (void) __ns_ldap_freeError(errorp); |
| *errorp = NULL; |
| } |
| /* else, exit */ |
| __s_api_deleteRefInfo(ref_list); |
| ref_list = NULL; |
| new_state = W_ERROR; |
| break; |
| } |
| /* target DN may changed due to referrals */ |
| if (current_ref->refDN) { |
| if (target_dn && target_dn_allocated) { |
| free(target_dn); |
| target_dn = NULL; |
| target_dn_allocated = FALSE; |
| } |
| target_dn = current_ref->refDN; |
| } |
| new_state = SELECT_OPERATION_SYNC; |
| break; |
| case W_LDAP_ERROR: |
| /* |
| * map error code and error message |
| * to password status if necessary. |
| * This is to see if password updates |
| * failed due to password policy or |
| * password syntax checking. |
| */ |
| if (errmsg) { |
| /* |
| * check if server supports |
| * password management |
| */ |
| passwd_mgmt = |
| __s_api_contain_passwd_control_oid( |
| conp->controls); |
| if (passwd_mgmt) |
| pwd_status = |
| __s_api_set_passwd_status( |
| Errno, errmsg); |
| ldap_memfree(errmsg); |
| errmsg = NULL; |
| } |
| |
| (void) sprintf(errstr, |
| gettext(ldap_err2string(Errno))); |
| err = strdup(errstr); |
| if (pwd_status != NS_PASSWD_GOOD) { |
| MKERROR_PWD_MGMT(*errorp, Errno, err, |
| pwd_status, 0, NULL); |
| } else { |
| MKERROR(LOG_INFO, *errorp, Errno, err, NULL); |
| } |
| return_rc = NS_LDAP_INTERNAL; |
| new_state = W_EXIT; |
| break; |
| case W_ERROR: |
| default: |
| (void) sprintf(errstr, |
| gettext("Internal write State machine exit" |
| " (state = %d, rc = %d)."), |
| err_state, return_rc); |
| err = strdup(errstr); |
| MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL); |
| new_state = W_EXIT; |
| break; |
| } |
| |
| if (new_state == W_ERROR) |
| err_state = state; |
| state = new_state; |
| } |
| |
| /* |
| * should never be here, the next line is to eliminating |
| * lint message |
| */ |
| return (NS_LDAP_INTERNAL); |
| } |
| |
| |
| /*ARGSUSED*/ |
| int |
| __ns_ldap_addAttr( |
| const char *service, |
| const char *dn, |
| const ns_ldap_attr_t * const *attr, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| LDAPMod **mods; |
| int rc = 0; |
| |
| #ifdef DEBUG |
| (void) fprintf(stderr, "__ns_ldap_addAttr START\n"); |
| #endif |
| *errorp = NULL; |
| |
| /* Sanity check */ |
| if ((attr == NULL) || (*attr == NULL) || |
| (dn == NULL) || (cred == NULL)) |
| return (NS_LDAP_INVALID_PARAM); |
| |
| mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags); |
| if (mods == NULL) { |
| return (NS_LDAP_MEMORY); |
| } |
| |
| rc = write_state_machine(LDAP_REQ_MODIFY, |
| (char *)dn, mods, cred, flags, errorp); |
| freeModList(mods); |
| |
| return (rc); |
| } |
| |
| |
| /*ARGSUSED*/ |
| int |
| __ns_ldap_delAttr( |
| const char *service, |
| const char *dn, |
| const ns_ldap_attr_t * const *attr, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| LDAPMod **mods; |
| int rc = 0; |
| |
| #ifdef DEBUG |
| (void) fprintf(stderr, "__ns_ldap_delAttr START\n"); |
| #endif |
| *errorp = NULL; |
| |
| /* Sanity check */ |
| if ((attr == NULL) || (*attr == NULL) || |
| (dn == NULL) || (cred == NULL)) |
| return (NS_LDAP_INVALID_PARAM); |
| |
| mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags); |
| if (mods == NULL) { |
| return (NS_LDAP_MEMORY); |
| } |
| |
| rc = write_state_machine(LDAP_REQ_MODIFY, |
| (char *)dn, mods, cred, flags, errorp); |
| |
| freeModList(mods); |
| return (rc); |
| } |
| |
| /*ARGSUSED*/ |
| int |
| __ns_ldap_repAttr( |
| const char *service, |
| const char *dn, |
| const ns_ldap_attr_t * const *attr, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| LDAPMod **mods; |
| int rc = 0; |
| |
| #ifdef DEBUG |
| (void) fprintf(stderr, "__ns_ldap_repAttr START\n"); |
| #endif |
| *errorp = NULL; |
| |
| /* Sanity check */ |
| if ((attr == NULL) || (*attr == NULL) || |
| (dn == NULL) || (cred == NULL)) |
| return (NS_LDAP_INVALID_PARAM); |
| mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags); |
| if (mods == NULL) { |
| return (NS_LDAP_MEMORY); |
| } |
| |
| rc = write_state_machine(LDAP_REQ_MODIFY, |
| (char *)dn, mods, cred, flags, errorp); |
| |
| freeModList(mods); |
| return (rc); |
| } |
| |
| |
| /*ARGSUSED*/ |
| int |
| __ns_ldap_addEntry( |
| const char *service, |
| const char *dn, |
| const ns_ldap_entry_t *entry, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| char *new_dn = NULL; |
| LDAPMod **mods = NULL; |
| const ns_ldap_attr_t * const *attr; |
| int nAttr = 0; |
| int rc = 0; |
| |
| #ifdef DEBUG |
| (void) fprintf(stderr, "__ns_ldap_addEntry START\n"); |
| #endif |
| |
| if ((entry == NULL) || (dn == NULL) || (cred == NULL)) |
| return (NS_LDAP_INVALID_PARAM); |
| *errorp = NULL; |
| |
| /* Construct array of LDAPMod representing attributes of new entry. */ |
| |
| nAttr = entry->attr_count; |
| attr = (const ns_ldap_attr_t * const *)(entry->attr_pair); |
| mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD, |
| nAttr, flags); |
| if (mods == NULL) { |
| return (NS_LDAP_MEMORY); |
| } |
| |
| rc = replace_mapped_attr_in_dn(service, dn, &new_dn); |
| if (rc != NS_LDAP_SUCCESS) { |
| freeModList(mods); |
| return (rc); |
| } |
| |
| rc = write_state_machine(LDAP_REQ_ADD, |
| new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp); |
| |
| if (new_dn) |
| free(new_dn); |
| freeModList(mods); |
| return (rc); |
| } |
| |
| |
| /*ARGSUSED*/ |
| int |
| __ns_ldap_delEntry( |
| const char *service, |
| const char *dn, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t ** errorp) |
| { |
| int rc; |
| |
| #ifdef DEBUG |
| (void) fprintf(stderr, "__ns_ldap_delEntry START\n"); |
| #endif |
| if ((dn == NULL) || (cred == NULL)) |
| return (NS_LDAP_INVALID_PARAM); |
| |
| *errorp = NULL; |
| |
| rc = write_state_machine(LDAP_REQ_DELETE, |
| (char *)dn, NULL, cred, flags, errorp); |
| |
| return (rc); |
| } |
| |
| /* |
| * Add Typed Entry Helper routines |
| */ |
| |
| /* |
| * Add Typed Entry Conversion routines |
| */ |
| |
| static int |
| __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value) |
| { |
| ns_ldap_attr_t *a; |
| char *v; |
| |
| a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); |
| if (a == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrname = strdup(attrname); |
| if (a->attrname == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrvalue = (char **)calloc(1, sizeof (char **)); |
| if (a->attrvalue == NULL) |
| return (NS_LDAP_MEMORY); |
| a->value_count = 1; |
| a->attrvalue[0] = NULL; |
| v = strdup(value); |
| if (v == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrvalue[0] = v; |
| e->attr_pair[e->attr_count] = a; |
| e->attr_count++; |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| static int |
| __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv) |
| { |
| ns_ldap_attr_t *a; |
| char *v; |
| char **av; |
| int i, j; |
| |
| a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t)); |
| if (a == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrname = strdup(attrname); |
| if (a->attrname == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| for (i = 0, av = argv; *av != NULL; av++, i++) |
| ; |
| |
| a->attrvalue = (char **)calloc(i, sizeof (char *)); |
| |
| if (a->attrvalue == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| a->value_count = i; |
| for (j = 0; j < i; j++) { |
| v = strdup(argv[j]); |
| if (v == NULL) |
| return (NS_LDAP_MEMORY); |
| a->attrvalue[j] = v; |
| } |
| e->attr_pair[e->attr_count] = a; |
| e->attr_count++; |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| static ns_ldap_entry_t * |
| __s_mk_entry(char **objclass, int max_attr) |
| { |
| ns_ldap_entry_t *e; |
| e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t)); |
| if (e == NULL) |
| return (NULL); |
| /* allocate attributes, +1 for objectclass, +1 for NULL terminator */ |
| e->attr_pair = (ns_ldap_attr_t **) |
| calloc(max_attr + 2, sizeof (ns_ldap_attr_t *)); |
| if (e->attr_pair == NULL) { |
| free(e); |
| return (NULL); |
| } |
| e->attr_count = 0; |
| if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) { |
| free(e->attr_pair); |
| free(e); |
| return (NULL); |
| } |
| return (e); |
| } |
| |
| |
| /* |
| * Conversion: passwd |
| * Input format: struct passwd |
| * Exported objectclass: posixAccount |
| */ |
| static int |
| __s_cvt_passwd(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct passwd *ptr; |
| int max_attr = 9; |
| char ibuf[10]; |
| static char *oclist[] = { |
| "posixAccount", |
| "shadowAccount", |
| "account", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct passwd *)data; |
| |
| if (ptr->pw_name == NULL || ptr->pw_uid < 0 || |
| ptr->pw_gid < 0 || ptr->pw_dir == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| rc = __s_add_attr(e, "uid", ptr->pw_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| rc = __s_add_attr(e, "cn", ptr->pw_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| if (ptr->pw_passwd != NULL && |
| ptr->pw_passwd[0] != '\0') { |
| rc = __s_add_attr(e, "userPassword", ptr->pw_passwd); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| #ifdef _LP64 |
| (void) sprintf(ibuf, "%d", ptr->pw_uid); |
| #else |
| (void) sprintf(ibuf, "%ld", ptr->pw_uid); |
| #endif |
| rc = __s_add_attr(e, "uidNumber", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| #ifdef _LP64 |
| (void) sprintf(ibuf, "%d", ptr->pw_gid); |
| #else |
| (void) sprintf(ibuf, "%ld", ptr->pw_gid); |
| #endif |
| rc = __s_add_attr(e, "gidNumber", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| if (ptr->pw_gecos != NULL && |
| ptr->pw_gecos[0] != '\0') { |
| rc = __s_add_attr(e, "gecos", ptr->pw_gecos); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| if (ptr->pw_shell != NULL && |
| ptr->pw_shell[0] != '\0') { |
| rc = __s_add_attr(e, "loginShell", ptr->pw_shell); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| /* |
| * Conversion: shadow |
| * Input format: struct shadow |
| * Exported objectclass: shadowAccount |
| */ |
| static int |
| __s_cvt_shadow(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct spwd *ptr; |
| int max_attr = 10; |
| char ibuf[10]; |
| static char *oclist[] = { |
| "posixAccount", |
| "shadowAccount", |
| "account", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct spwd *)data; |
| |
| if (ptr->sp_namp == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| rc = __s_add_attr(e, "uid", ptr->sp_namp); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| if (ptr->sp_pwdp == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_INVALID_PARAM); |
| } else { |
| rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_lstchg >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_lstchg); |
| rc = __s_add_attr(e, "shadowLastChange", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_min >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_min); |
| rc = __s_add_attr(e, "shadowMin", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_max >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_max); |
| rc = __s_add_attr(e, "shadowMax", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_warn >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_warn); |
| rc = __s_add_attr(e, "shadowWarning", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_inact >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_inact); |
| rc = __s_add_attr(e, "shadowInactive", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->sp_expire >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->sp_expire); |
| rc = __s_add_attr(e, "shadowExpire", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| (void) sprintf(ibuf, "%d", ptr->sp_flag); |
| rc = __s_add_attr(e, "shadowFlag", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| |
| /* |
| * Conversion: group |
| * Input format: struct group |
| * Exported objectclass: posixGroup |
| */ |
| static int |
| __s_cvt_group(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct group *ptr; |
| int i, j, k; |
| char **nm, **lm; |
| int max_attr = 4; |
| char ibuf[10]; |
| static char *oclist[] = { |
| "posixGroup", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct group *)data; |
| |
| if (ptr->gr_name == NULL || ptr->gr_gid < 0) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| rc = __s_add_attr(e, "cn", ptr->gr_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| #ifdef _LP64 |
| (void) sprintf(ibuf, "%d", ptr->gr_gid); |
| #else |
| (void) sprintf(ibuf, "%ld", ptr->gr_gid); |
| #endif |
| rc = __s_add_attr(e, "gidNumber", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') { |
| rc = __s_add_attr(e, "userPassword", ptr->gr_passwd); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| if (ptr->gr_mem && ptr->gr_mem[0]) { |
| lm = ptr->gr_mem; |
| for (i = 0; *lm; i++, lm++) |
| ; |
| lm = ptr->gr_mem; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) { |
| nm[j] = strdup(lm[j]); |
| if (nm[j] == NULL) { |
| for (k = 0; k < j; k++) |
| free(nm[k]); |
| free(nm); |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| } |
| rc = __s_add_attrlist(e, "memberUid", nm); |
| for (j = 0; j < i; j++) { |
| free(nm[j]); |
| } |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| /* |
| * Conversion: hosts |
| * Input format: struct hostent |
| * Exported objectclass: ipHost |
| */ |
| static int |
| __s_cvt_hosts(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct hostent *ptr; |
| int max_attr = 6; |
| int i, j, k; |
| char **nm, **lm; |
| static char *oclist[] = { |
| "ipHost", |
| "device", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct hostent *)data; |
| |
| if (ptr->h_name == NULL || |
| ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s", |
| ptr->h_name, ptr->h_addr_list[0]); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->h_aliases && ptr->h_aliases[0]) { |
| lm = ptr->h_aliases; |
| for (i = 0; *lm; i++, lm++) |
| ; |
| lm = ptr->h_aliases; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| nm[0] = ptr->h_name; |
| for (j = 0; j < i; j++) |
| nm[j+1] = ptr->h_aliases[j]; |
| |
| rc = __s_add_attrlist(e, "cn", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| rc = __s_add_attr(e, "cn", ptr->h_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| if (ptr->h_addr_list && ptr->h_addr_list[0]) { |
| lm = ptr->h_addr_list; |
| for (i = 0; *lm; i++, lm++) |
| ; |
| lm = ptr->h_addr_list; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) { |
| nm[j] = strdup(lm[j]); |
| if (nm[j] == NULL) { |
| for (k = 0; k < j; k++) |
| free(nm[k]); |
| free(nm); |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| } |
| rc = __s_add_attrlist(e, "ipHostNumber", nm); |
| for (j = 0; j < i; j++) { |
| free(nm[j]); |
| } |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| /* |
| * Conversion: rpc |
| * Input format: struct rpcent |
| * Exported objectclass: oncRpc |
| */ |
| static int |
| __s_cvt_rpc(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct rpcent *ptr; |
| int max_attr = 3; |
| int i, j; |
| char **nm; |
| char ibuf[10]; |
| static char *oclist[] = { |
| "oncRpc", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct rpcent *)data; |
| |
| if (ptr->r_name == NULL || ptr->r_number < 0) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->r_aliases && ptr->r_aliases[0]) { |
| nm = ptr->r_aliases; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| nm[0] = ptr->r_name; |
| for (j = 0; j < i; j++) |
| nm[j+1] = ptr->r_aliases[j]; |
| |
| rc = __s_add_attrlist(e, "cn", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| rc = __s_add_attr(e, "cn", ptr->r_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| if (ptr->r_number >= 0) { |
| (void) sprintf(ibuf, "%d", ptr->r_number); |
| rc = __s_add_attr(e, "oncRpcNumber", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| |
| /* |
| * Conversion: protocols |
| * Input format: struct protoent |
| * Exported objectclass: ipProtocol |
| */ |
| static int |
| __s_cvt_protocols(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct protoent *ptr; |
| int max_attr = 3; |
| int i, j; |
| char ibuf[10]; |
| char **nm; |
| static char *oclist[] = { |
| "ipProtocol", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct protoent *)data; |
| |
| if (ptr->p_name == NULL || ptr->p_proto < 0) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->p_aliases && ptr->p_aliases[0]) { |
| nm = ptr->p_aliases; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| nm[0] = ptr->p_name; |
| for (j = 0; j < i; j++) |
| nm[j+1] = ptr->p_aliases[j]; |
| |
| rc = __s_add_attrlist(e, "cn", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| rc = __s_add_attr(e, "cn", ptr->p_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| (void) sprintf(ibuf, "%d", ptr->p_proto); |
| rc = __s_add_attr(e, "ipProtocolNumber", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| |
| /* |
| * Conversion: services |
| * Input format: struct servent |
| * Exported objectclass: ipService |
| */ |
| static int |
| __s_cvt_services(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct servent *ptr; |
| int max_attr = 4; |
| int i, j; |
| char ibuf[10]; |
| char **nm; |
| static char *oclist[] = { |
| "ipService", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct servent *)data; |
| |
| if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s", |
| ptr->s_name, ptr->s_proto); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->s_aliases && ptr->s_aliases[0]) { |
| nm = ptr->s_aliases; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| nm[0] = ptr->s_name; |
| for (j = 0; j < i; j++) |
| nm[j+1] = ptr->s_aliases[j]; |
| |
| rc = __s_add_attrlist(e, "cn", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| rc = __s_add_attr(e, "cn", ptr->s_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| (void) sprintf(ibuf, "%d", ptr->s_port); |
| rc = __s_add_attr(e, "ipServicePort", ibuf); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| |
| /* |
| * Conversion: networks |
| * Input format: struct netent |
| * Exported objectclass: ipNetwork |
| */ |
| static int |
| __s_cvt_networks(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct netent *ptr; |
| int max_attr = 4; |
| int i, j; |
| char cp[64]; |
| char **nm; |
| static char *oclist[] = { |
| "ipNetwork", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct netent *)data; |
| |
| if (ptr->n_name == NULL || ptr->n_net == 0) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d", |
| (ptr->n_net & 0xFF000000) >> 24, |
| (ptr->n_net & 0x00FF0000) >> 16, |
| (ptr->n_net & 0x0000FF00) >> 8, |
| (ptr->n_net & 0x000000FF)); |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->n_aliases && ptr->n_aliases[0]) { |
| nm = ptr->n_aliases; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| nm[0] = ptr->n_name; |
| for (j = 0; j < i; j++) |
| nm[j+1] = ptr->n_aliases[j]; |
| |
| rc = __s_add_attrlist(e, "cn", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } else { |
| rc = __s_add_attr(e, "cn", ptr->n_name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| rc = __s_add_attr(e, "ipNetworkNumber", cp); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| /* |
| * Conversion: netmasks |
| * Input format: struct _ns_netmasks |
| * Exported objectclass: ipNetwork |
| */ |
| static int |
| __s_cvt_netmasks(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_netmasks *ptr; |
| int max_attr = 4; |
| static char *oclist[] = { |
| "ipNetwork", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_netmasks *)data; |
| |
| if (ptr->netnumber == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| if (ptr->netmask != '\0') { |
| rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| /* |
| * Conversion: netgroups |
| * Input format: struct _ns_netgroups |
| * Exported objectclass: nisNetgroup |
| */ |
| static int |
| __s_cvt_netgroups(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_netgroups *ptr; |
| int max_attr = 6; |
| int i, j; |
| char **nm; |
| static char *oclist[] = { |
| "nisNetgroup", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_netgroups *)data; |
| |
| if (ptr->name == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| if (ptr->name != '\0') { |
| rc = __s_add_attr(e, "cn", ptr->name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->triplet && ptr->triplet[0]) { |
| nm = ptr->triplet; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) |
| nm[j] = ptr->triplet[j]; |
| |
| rc = __s_add_attrlist(e, "nisNetgroupTriple", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| if (ptr->netgroup && ptr->netgroup[0]) { |
| nm = ptr->netgroup; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) |
| nm[j] = ptr->netgroup[j]; |
| |
| rc = __s_add_attrlist(e, "memberNisNetgroup", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| return (NS_LDAP_SUCCESS); |
| } |
| /* |
| * Conversion: bootparams |
| * Input format: struct _ns_bootp |
| * Exported objectclass: bootableDevice, device |
| */ |
| static int |
| __s_cvt_bootparams(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_bootp *ptr; |
| int max_attr = 4; |
| int i, j; |
| char **nm; |
| static char *oclist[] = { |
| "bootableDevice", |
| "device", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_bootp *)data; |
| |
| if (ptr->name == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| if (ptr->name != '\0') { |
| rc = __s_add_attr(e, "cn", ptr->name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->param && ptr->param[0]) { |
| nm = ptr->param; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) |
| nm[j] = ptr->param[j]; |
| |
| rc = __s_add_attrlist(e, "bootParameter", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| /* |
| * Conversion: ethers |
| * Input format: struct _ns_ethers |
| * Exported objectclass: ieee802Device, device |
| */ |
| static int |
| __s_cvt_ethers(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_ethers *ptr; |
| int max_attr = 4; |
| static char *oclist[] = { |
| "ieee802Device", |
| "device", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_ethers *)data; |
| |
| if (ptr->name == NULL || ptr->ether == '\0') { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| rc = __s_add_attr(e, "cn", ptr->name); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| rc = __s_add_attr(e, "macAddress", ptr->ether); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| /* |
| * This function is used when processing an ethers (objectclass: ieee802Device) |
| * or a bootparams (objectclass: bootableDevice) entry, and the entry is |
| * already found in LDAP. Since both ethers and bootparams share the same |
| * LDAP container, we want to check that the entry found in LDAP is: |
| * - either the same entry (same cn, same objectclass): we don't do anything |
| * in this case |
| * - or an entry which does not have the objectclass we are interesting in: |
| * in this case, we modify the existing entry by adding the relevant |
| * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s) |
| * from the attribute list previously computing by the relevant conversion |
| * function. |
| * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams() |
| * we know that there is only 1 more attribute today to add (macAddress |
| * or bootParameter) |
| */ |
| #define _MAX_ATTR_ETHBOOTP 2 |
| static int |
| modify_ethers_bootp( |
| const char *service, |
| const char *rdn, |
| const char *fulldn, |
| const ns_ldap_attr_t * const *attrlist, |
| const ns_cred_t *cred, |
| const int flags, |
| ns_ldap_error_t **errorp) |
| { |
| char filter[BUFSIZ]; |
| ns_ldap_result_t *resultp; |
| int rc = 0; |
| int i; |
| ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1]; |
| ns_ldap_attr_t new_attrlist0; |
| char *new_attrvalue0[1]; |
| const ns_ldap_attr_t * const *aptr = attrlist; |
| ns_ldap_attr_t *aptr2; |
| ns_ldap_error_t *new_errorp = NULL; |
| |
| if (rdn == NULL || fulldn == NULL || attrlist == NULL || |
| errorp == NULL || service == NULL) |
| return (NS_LDAP_OP_FAILED); |
| |
| bzero(&new_attrlist, sizeof (new_attrlist)); |
| bzero(&new_attrlist0, sizeof (new_attrlist0)); |
| new_attrlist[0] = &new_attrlist0; |
| new_attrlist[0]->attrvalue = new_attrvalue0; |
| |
| new_attrlist[0]->attrname = "objectclass"; |
| new_attrlist[0]->value_count = 1; |
| if (strcasecmp(service, "ethers") == NULL) { |
| (void) snprintf(&filter[0], sizeof (filter), |
| "(&(objectClass=ieee802Device)(%s))", |
| rdn); |
| new_attrlist[0]->attrvalue[0] = "ieee802Device"; |
| } else { |
| (void) snprintf(&filter[0], sizeof (filter), |
| "(&(objectClass=bootableDevice)(%s))", |
| rdn); |
| new_attrlist[0]->attrvalue[0] = "bootableDevice"; |
| } |
| |
| rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL, |
| NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp, |
| NULL, NULL); |
| |
| switch (rc) { |
| case NS_LDAP_SUCCESS: |
| /* |
| * entry already exists for this service |
| * return NS_LDAP_INTERNAL and do not modify the incoming errorp |
| */ |
| rc = NS_LDAP_INTERNAL; |
| break; |
| case NS_LDAP_NOTFOUND: |
| /* |
| * entry not found with the given objectclasss but entry exists |
| * hence add the relevant attribute (macAddress or bootparams). |
| */ |
| i = 1; |
| while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) { |
| /* aptr2 needed here to avoid lint warning */ |
| aptr2 = (ns_ldap_attr_t *)*aptr++; |
| if ((strcasecmp(aptr2->attrname, "cn") != 0) && |
| (strcasecmp(aptr2->attrname, |
| "objectclass") != 0)) { |
| new_attrlist[i++] = (ns_ldap_attr_t *)aptr2; |
| } |
| } |
| |
| if (i != _MAX_ATTR_ETHBOOTP) { |
| /* we haven't found all expected attributes */ |
| rc = NS_LDAP_OP_FAILED; |
| break; |
| } |
| |
| aptr = (const ns_ldap_attr_t * const *) new_attrlist; |
| /* clean errorp first */ |
| (void) __ns_ldap_freeError(errorp); |
| rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags, |
| errorp); |
| break; |
| default: |
| /* |
| * unexpected error happenned |
| * returning relevant error |
| */ |
| (void) __ns_ldap_freeError(errorp); |
| *errorp = new_errorp; |
| break; |
| } |
| |
| return (rc); |
| } |
| |
| /* |
| * Conversion: publickey |
| * Input format: struct _ns_pubkey |
| * Exported objectclass: NisKeyObject |
| */ |
| static int |
| __s_cvt_publickey(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_pubkey *ptr; |
| int max_attr = 3; |
| static char *oclist[] = { |
| "NisKeyObject", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_pubkey *)data; |
| |
| if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| if (ptr->hostcred == NS_HOSTCRED_FALSE) |
| (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name); |
| else |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| /* Error check the data and add the attributes */ |
| |
| rc = __s_add_attr(e, "nisPublickey", ptr->pubkey); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| rc = __s_add_attr(e, "nisSecretkey", ptr->privkey); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| } |
| /* |
| * Conversion: aliases |
| * Input format: struct _ns_alias |
| * Exported objectclass: mailGroup |
| */ |
| static int |
| __s_cvt_aliases(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| ns_ldap_entry_t *e; |
| int rc; |
| char trdn[RDNSIZE]; |
| /* routine specific */ |
| struct _ns_alias *ptr; |
| int max_attr = 4; |
| int i, j; |
| char **nm; |
| static char *oclist[] = { |
| "mailGroup", |
| "top", |
| NULL |
| }; |
| |
| if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL) |
| return (NS_LDAP_OP_FAILED); |
| *entry = e = __s_mk_entry(oclist, max_attr); |
| if (e == NULL) |
| return (NS_LDAP_MEMORY); |
| |
| /* Convert the structure */ |
| ptr = (struct _ns_alias *)data; |
| |
| if (ptr->alias == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_INVALID_PARAM); |
| } |
| |
| /* Create an appropriate rdn */ |
| (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias); |
| *rdn = strdup(trdn); |
| if (*rdn == NULL) { |
| __ns_ldap_freeEntry(e); |
| *entry = NULL; |
| return (NS_LDAP_MEMORY); |
| } |
| |
| if (ptr->alias != '\0') { |
| rc = __s_add_attr(e, "mail", (char *)ptr->alias); |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| /* Error check the data and add the attributes */ |
| if (ptr->member && ptr->member[0]) { |
| nm = ptr->member; |
| for (i = 0; *nm; i++, nm++) |
| ; |
| nm = (char **)calloc(i+2, sizeof (char *)); |
| if (nm == NULL) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (NS_LDAP_MEMORY); |
| } |
| for (j = 0; j < i; j++) |
| nm[j] = ptr->member[j]; |
| |
| rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm); |
| free(nm); |
| nm = NULL; |
| if (rc != NS_LDAP_SUCCESS) { |
| __s_cvt_freeEntryRdn(entry, rdn); |
| return (rc); |
| } |
| } |
| |
| return (NS_LDAP_SUCCESS); |
| |
| } |
| /* |
| * Conversion: automount |
| * Input format: struct _ns_automount |
| * Exported objectclass: automount |
| */ |
| static int |
| __s_cvt_auto_mount(const void *data, char **rdn, |
| ns_ldap_entry_t **entry, ns_ldap_error_t **errorp) |
| { |
| <