9169 libsldap: comparison between pointer and zero character constant
[unleashed.git] / usr / src / lib / libsldap / common / ns_writes.c
blob5029598f197c76ff6eb30c1e6400bb0068589782
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2012 Milan Jurik. All rights reserved.
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <stdlib.h>
30 #include <libintl.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <strings.h>
37 #include <lber.h>
38 #include <ldap.h>
39 #include <syslog.h>
40 #include <stddef.h>
41 #include <sys/mman.h>
43 #include "ns_sldap.h"
44 #include "ns_internal.h"
45 #include "ns_connmgmt.h"
46 #include "ns_cache_door.h"
48 /* Additional headers for addTypedEntry Conversion routines */
49 #include <pwd.h>
50 #include <project.h>
51 #include <shadow.h>
52 #include <grp.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 #include <netdb.h>
56 #include <rpc/rpcent.h>
57 #include <auth_attr.h>
58 #include <exec_attr.h>
59 #include <prof_attr.h>
60 #include <user_attr.h>
61 #include <bsm/libbsm.h>
62 #include <sys/tsol/tndb.h>
63 #include <tsol/label.h>
65 static int send_to_cachemgr(const char *,
66 ns_ldap_attr_t **, ns_ldap_error_t **);
68 static int escape_str(char *, char *);
71 * If the rdn is a mapped attr:
72 * return NS_LDAP_SUCCESS and a new_dn.
73 * If no mapped attr is found in the rdn:
74 * return NS_LDAP_SUCCESS and *new_dn == NULL
75 * For example:
76 * service = abc
77 * dn = cn=foo,dc=bar,dc=com
78 * attributeMapping: abc:cn=sn
79 * Then:
80 * new_dn = sn=foo,dc=bar,dc=com
83 static int
84 replace_mapped_attr_in_dn(
85 const char *service, const char *dn, char **new_dn)
87 char **mappedattr;
88 char **dnArray = NULL;
89 char *rservice;
90 char *cur = NULL;
91 int len = 0, orig_len = 0, mapped_len = 0;
92 int dn_len = 0;
94 *new_dn = NULL;
97 * separate dn into individual componets
98 * e.g.
99 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
101 dnArray = ldap_explode_dn(dn, 0);
102 if (!dnArray || !*dnArray)
103 return (NS_LDAP_INVALID_PARAM);
105 cur = strchr(dnArray[0], '=');
106 if (!cur) {
107 __s_api_free2dArray(dnArray);
108 return (NS_LDAP_INVALID_PARAM);
110 *cur = '\0';
112 /* we only check schema mapping for automount, not for auto_* */
113 if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
114 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
115 rservice = "automount";
116 else
117 rservice = (char *)service;
119 mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]);
120 if (!mappedattr || !mappedattr[0]) {
121 __s_api_free2dArray(dnArray);
122 if (mappedattr)
123 __s_api_free2dArray(mappedattr);
124 return (NS_LDAP_SUCCESS);
126 orig_len = strlen(dnArray[0]);
129 * The new length is *dn length + (difference between
130 * orig attr and mapped attr) + 1 ;
131 * e.g.
132 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
133 * ==>
134 * cn=aa,automountMapName=auto_home,dc=foo,dc=com
136 mapped_len = strlen(mappedattr[0]);
137 dn_len = strlen(dn);
138 len = dn_len - orig_len + mapped_len + 1;
139 *new_dn = (char *)calloc(1, len);
140 if (*new_dn == NULL) {
141 __s_api_free2dArray(dnArray);
142 __s_api_free2dArray(mappedattr);
143 return (NS_LDAP_MEMORY);
146 (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
147 __s_api_free2dArray(dnArray);
148 __s_api_free2dArray(mappedattr);
150 return (NS_LDAP_SUCCESS);
155 * The following function is only used by the
156 * "gecos" 1 to N attribute mapping code. It expects
157 * and handle only one data/length pair.
159 static int
160 init_bval_mod(
161 LDAPMod *mod,
162 int mop,
163 char *mtype,
164 char *mvptr,
165 int mvlen)
168 struct berval **bmodval;
170 /* dup attribute name */
171 mod->mod_type = strdup(mtype);
172 if (mod->mod_type == NULL)
173 return (-1);
176 * assume single value,
177 * since only one value/length pair passed in
179 bmodval = (struct berval **)calloc(2, sizeof (struct berval *));
180 if (bmodval == NULL) {
181 free(mod->mod_type);
182 mod->mod_type = NULL;
183 return (-1);
185 bmodval[0] = (struct berval *)calloc(1, sizeof (struct berval));
186 if (bmodval[0] == NULL) {
187 free(mod->mod_type);
188 mod->mod_type = NULL;
189 free(bmodval);
190 return (-1);
193 /* set pointer to data */
194 bmodval[0]->bv_val = mvptr;
196 /* set length */
197 bmodval[0]->bv_len = mvlen;
200 * turn on the BVALUE bit to indicate
201 * that the length of data is supplied
203 mod->mod_op = mop | LDAP_MOD_BVALUES;
205 mod->mod_bvalues = bmodval;
207 return (0);
210 static void
211 freeModList(LDAPMod **mods)
213 int i, j;
214 int name_is_oc;
216 if (mods == NULL)
217 return;
219 for (i = 0; mods[i]; i++) {
221 /* free attribute name */
222 name_is_oc = FALSE;
223 if (mods[i]->mod_type) {
224 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0)
225 name_is_oc = TRUE;
226 free(mods[i]->mod_type);
229 if (mods[i]->mod_bvalues == NULL)
230 continue;
232 * LDAP_MOD_BVALUES is only set by
233 * the "gecos" 1 to N attribute mapping
234 * code, and the attribute is single valued.
236 if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
237 if (mods[i]->mod_bvalues[0])
238 free(mods[i]->mod_bvalues[0]);
239 } else {
240 if (name_is_oc) {
242 * only values for the "objectclass"
243 * were dupped using strdup.
244 * other attribute values were
245 * not dupped, but via pointer
246 * assignment. So here the
247 * values for "objectclass"
248 * is freed one by one,
249 * but the values for other
250 * attributes need not be freed.
252 for (j = 0; mods[i]->mod_values[j]; j++)
253 free(mods[i]->mod_values[j]);
257 free(mods[i]->mod_bvalues);
260 /* modlist */
261 free((char *)(mods[0]));
262 free(mods);
265 static LDAPMod **
266 __s_api_makeModListCount(
267 const char *service,
268 const ns_ldap_attr_t * const *attr,
269 const int mod_op,
270 const int count,
271 const int flags)
273 LDAPMod **mods, *modlist;
274 char **modval;
275 char **mapping;
276 int i;
277 int j;
278 int k, rc, vlen;
279 char *c, *comma1 = NULL, *comma2 = NULL;
280 int schema_mapping_existed = FALSE;
281 int auto_service = FALSE;
285 * add 2 for "gecos" 1 to up to 3 attribute mapping
287 mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
288 if (mods == NULL) {
289 return (NULL);
292 * add 2 for "gecos" 1 to up to 3 attribute mapping
294 modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
295 if (modlist == NULL) {
296 free(mods);
297 return (NULL);
300 if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
301 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
302 auto_service = TRUE;
305 * see if schema mapping existed for the given service
307 mapping = __ns_ldap_getOrigAttribute(service,
308 NS_HASH_SCHEMA_MAPPING_EXISTED);
309 if (mapping) {
310 schema_mapping_existed = TRUE;
311 __s_api_free2dArray(mapping);
312 mapping = NULL;
315 for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
316 mods[i] = &modlist[i];
317 mods[i]->mod_op = mod_op;
319 * Perform attribute mapping if necessary.
321 if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) {
322 mapping = __ns_ldap_getMappedAttributes(service,
323 attr[k]->attrname);
324 } else
325 mapping = NULL;
327 if (mapping == NULL && auto_service &&
328 (flags & NS_LDAP_NOMAP) == 0) {
330 * if service == auto_xxx and
331 * no mapped attribute is found
332 * and NS_LDAP_NOMAP is not set
333 * then try automount's mapped attribute
335 mapping = __ns_ldap_getMappedAttributes("automount",
336 attr[k]->attrname);
339 if (mapping == NULL) {
340 mods[i]->mod_type = strdup(attr[k]->attrname);
341 if (mods[i]->mod_type == NULL)
342 goto free_memory;
343 } else {
345 * 1 to N attribute mapping is only done for "gecos",
346 * and only 1 to 3 mapping.
347 * nine cases here:
349 * A. attrMap=passwd:gecos=a
350 * 1. gecos="xx,yy,zz" -> a="xx,yy,zz"
351 * 2. gecos="xx,yy" -> a="xx,yy"
352 * 3. gecos="xx" -> a="xx"
354 * B. attrMap=passwd:gecos=a b
355 * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
356 * 5. gecos="xx,yy" -> a="xx" b="yy"
357 * 6. gecos="xx" -> a="xx"
359 * C. attrMap=passwd:gecos=a b c
360 * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
361 * 8. gecos="xx,yy" -> a="xx" b="yy"
362 * 9. gecos="xx" -> a="xx"
364 * This can be grouped as:
366 * c1 cases: 1,2,3,6,9
367 * if ((attrMap=passwd:gecos=a) ||
368 * (no "," in gecos value))
369 * same as other no-mapping attributes,
370 * no special processing needed
371 * else
373 * c2 cases: 4,5,8
374 * if ((attrMap=passwd:gecos=a b) ||
375 * (only one "," in gecos value))
376 * a=xx b=yy[,...]
377 * else
379 * c3 case: 7
380 * a=xx b=yy c=...
382 * notes: in case c2 and c3, ... could still contain ","
384 if (strcasecmp(service, "passwd") == 0 &&
385 strcasecmp(attr[k]->attrname, "gecos") == 0 &&
386 mapping[1] && attr[k]->attrvalue[0] &&
387 (comma1 = strchr(attr[k]->attrvalue[0],
388 COMMATOK)) != NULL) {
390 /* is there a second comma? */
391 if (*(comma1 + 1) != '\0')
392 comma2 = strchr(comma1 + 1, COMMATOK);
395 * Process case c2 or c3.
396 * case c2: mapped to two attributes or just
397 * one comma
399 if (mapping[2] == NULL || comma2 == NULL) {
400 /* case c2 */
403 * int mod structure for the first attribute
405 vlen = comma1 - attr[k]->attrvalue[0];
406 c = attr[k]->attrvalue[0];
408 if (vlen > 0 && c) {
409 rc = init_bval_mod(mods[i], mod_op,
410 mapping[0], c, vlen);
411 if (rc != 0)
412 goto free_memory;
413 } else {
414 /* don't leave a hole in mods array */
415 mods[i] = NULL;
416 i--;
421 * init mod structure for the 2nd attribute
423 if (*(comma1 + 1) == '\0') {
424 __s_api_free2dArray(mapping);
425 mapping = NULL;
426 continue;
429 i++;
430 mods[i] = &modlist[i];
433 * get pointer to data.
434 * Skip leading spaces.
436 for (c = comma1 + 1; *c == SPACETOK; c++) {
437 /* empty */
440 /* get data length */
441 vlen = strlen(attr[k]->attrvalue[0]) -
442 (c - attr[k]->attrvalue[0]);
444 if (vlen > 0 && c) {
445 rc = init_bval_mod(mods[i], mod_op,
446 mapping[1], c, vlen);
447 if (rc != 0)
448 goto free_memory;
449 } else {
450 /* don't leave a hole in mods array */
451 mods[i] = NULL;
452 i--;
455 /* done with the mapping array */
456 __s_api_free2dArray(mapping);
457 mapping = NULL;
459 continue;
460 } else {
461 /* case c3 */
464 * int mod structure for the first attribute
466 vlen = comma1 - attr[k]->attrvalue[0];
467 c = attr[k]->attrvalue[0];
469 if (vlen > 0 && c) {
470 rc = init_bval_mod(mods[i], mod_op,
471 mapping[0], c, vlen);
472 if (rc != 0)
473 goto free_memory;
474 } else {
475 /* don't leave a hole in mods array */
476 mods[i] = NULL;
477 i--;
481 * init mod structure for the 2nd attribute
483 i++;
484 mods[i] = &modlist[i];
487 * get pointer to data.
488 * Skip leading spaces.
490 for (c = comma1 + 1; *c == SPACETOK; c++) {
491 /* empty */
494 /* get data length */
495 vlen = comma2 - c;
497 if (vlen > 0 && c) {
498 rc = init_bval_mod(mods[i], mod_op,
499 mapping[1], c, vlen);
500 if (rc != 0)
501 goto free_memory;
502 } else {
503 /* don't leave a hole in mods array */
504 mods[i] = NULL;
505 i--;
509 * init mod structure for the 3rd attribute
511 if (*(comma2 + 1) == '\0') {
512 __s_api_free2dArray(mapping);
513 mapping = NULL;
514 continue;
517 i++;
518 mods[i] = &modlist[i];
520 * get pointer to data.
521 * Skip leading spaces.
523 for (c = comma2 + 1; *c == SPACETOK; c++) {
524 /* empty */
527 /* get data length */
528 vlen = strlen(attr[k]->attrvalue[0]) -
529 (c - attr[k]->attrvalue[0]);
531 if (vlen > 0 && c) {
532 rc = init_bval_mod(mods[i], mod_op,
533 mapping[2], c, vlen);
534 if (rc != 0)
535 goto free_memory;
536 } else {
537 /* don't leave a hole in mods array */
538 mods[i] = NULL;
539 i--;
542 /* done with the mapping array */
543 __s_api_free2dArray(mapping);
544 mapping = NULL;
546 continue;
550 /* case c1 */
551 mods[i]->mod_type = strdup(mapping[0]);
552 if (mods[i]->mod_type == NULL) {
553 goto free_memory;
555 __s_api_free2dArray(mapping);
556 mapping = NULL;
559 modval = (char **)calloc(attr[k]->value_count+1,
560 sizeof (char *));
561 if (modval == NULL)
562 goto free_memory;
564 * Perform objectclass mapping.
565 * Note that the values for the "objectclass" attribute
566 * will be dupped using strdup. Values for other
567 * attributes will be referenced via pointer
568 * assignments.
570 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
571 for (j = 0; j < attr[k]->value_count; j++) {
572 if (schema_mapping_existed &&
573 (flags & NS_LDAP_NOMAP) == 0)
574 mapping =
575 __ns_ldap_getMappedObjectClass(
576 service, attr[k]->attrvalue[j]);
577 else
578 mapping = NULL;
580 if (mapping == NULL && auto_service &&
581 (flags & NS_LDAP_NOMAP) == 0)
583 * if service == auto_xxx and
584 * no mapped objectclass is found
585 * then try automount
587 mapping =
588 __ns_ldap_getMappedObjectClass(
589 "automount", attr[k]->attrvalue[j]);
591 if (mapping && mapping[0]) {
592 /* assume single mapping */
593 modval[j] = strdup(mapping[0]);
594 } else {
595 modval[j] = strdup(attr[k]->
596 attrvalue[j]);
598 if (modval[j] == NULL)
599 goto free_memory;
601 } else {
602 for (j = 0; j < attr[k]->value_count; j++) {
603 /* ASSIGN NOT COPY */
604 modval[j] = attr[k]->attrvalue[j];
607 mods[i]->mod_values = modval;
610 return (mods);
612 free_memory:
613 freeModList(mods);
614 if (mapping)
615 __s_api_free2dArray(mapping);
617 return (NULL);
621 static LDAPMod **
622 __s_api_makeModList(
623 const char *service,
624 const ns_ldap_attr_t * const *attr,
625 const int mod_op,
626 const int flags)
628 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
629 int count = 0;
631 if (aptr == NULL)
632 return (NULL);
634 /* count number of attributes */
635 while (*aptr++)
636 count++;
638 return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
641 static void
642 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
644 if (*entry != NULL) {
645 __ns_ldap_freeEntry(*entry);
646 *entry = NULL;
648 if (*rdn != NULL) {
649 free(*rdn);
650 *rdn = NULL;
655 * This state machine performs one or more LDAP add/delete/modify
656 * operations to configured LDAP servers.
658 static int
659 write_state_machine(
660 int ldap_op,
661 char *dn,
662 LDAPMod **mods,
663 const ns_cred_t *cred,
664 const int flags,
665 ns_ldap_error_t ** errorp)
667 ConnectionID connectionId = -1;
668 Connection *conp = NULL;
669 LDAPMessage *res;
670 char *target_dn = NULL;
671 char errstr[MAXERROR];
672 int rc = NS_LDAP_SUCCESS;
673 int return_rc = NS_LDAP_SUCCESS;
674 int followRef = FALSE;
675 int target_dn_allocated = FALSE;
676 int len;
677 int msgid;
678 int Errno;
679 boolean_t from_get_lderrno = B_FALSE;
680 int always = 1;
681 char *err, *errmsg = NULL;
682 /* referrals returned by the LDAP operation */
683 char **referrals = NULL;
685 * list of referrals used by the state machine, built from
686 * the referrals variable above
688 ns_referral_info_t *ref_list = NULL;
689 /* current referral */
690 ns_referral_info_t *current_ref = NULL;
691 ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
692 int do_not_fail_if_new_pwd_reqd = 0;
693 ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD;
694 int passwd_mgmt = 0;
695 int i = 0;
696 int ldap_error;
697 int nopasswd_acct_mgmt = 0;
698 ns_conn_user_t *conn_user = NULL;
700 while (always) {
701 switch (state) {
702 case W_EXIT:
703 /* return the MT connection and free the conn user */
704 if (conn_user != NULL) {
705 if (conn_user->use_mt_conn == B_TRUE) {
706 if (conn_user->ns_error != NULL) {
707 *errorp = conn_user->ns_error;
708 conn_user->ns_error = NULL;
709 return_rc = conn_user->ns_rc;
711 if (conn_user->conn_mt != NULL)
712 __s_api_conn_mt_return(
713 conn_user);
715 __s_api_conn_user_free(conn_user);
718 if (connectionId > -1)
719 DropConnection(connectionId, NS_LDAP_NEW_CONN);
720 if (ref_list)
721 __s_api_deleteRefInfo(ref_list);
722 if (target_dn && target_dn_allocated)
723 free(target_dn);
724 return (return_rc);
725 case W_INIT:
726 /* see if need to follow referrals */
727 rc = __s_api_toFollowReferrals(flags,
728 &followRef, errorp);
729 if (rc != NS_LDAP_SUCCESS) {
730 return_rc = rc;
731 new_state = W_ERROR;
732 break;
734 len = strlen(dn);
735 if (dn[len-1] == COMMATOK)
736 rc = __s_api_append_default_basedn(
737 dn, &target_dn, &target_dn_allocated,
738 errorp);
739 else
740 target_dn = dn;
741 if (rc != NS_LDAP_SUCCESS) {
742 return_rc = rc;
743 new_state = W_ERROR;
745 else
746 new_state = GET_CONNECTION;
747 break;
748 case GET_CONNECTION:
749 /* identify self as a write user */
750 conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE,
751 NULL, B_FALSE);
752 rc = __s_api_getConnection(NULL,
753 flags, cred, &connectionId, &conp, errorp,
754 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
755 conn_user);
758 * If password control attached
759 * in *errorp,
760 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
761 * free the error structure (we do not need
762 * the password management info).
763 * Reset rc to NS_LDAP_SUCCESS.
765 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
766 (void) __ns_ldap_freeError(errorp);
767 *errorp = NULL;
768 rc = NS_LDAP_SUCCESS;
771 if (rc != NS_LDAP_SUCCESS) {
772 return_rc = rc;
773 new_state = W_ERROR;
774 break;
776 if (followRef)
777 new_state = SELECT_OPERATION_ASYNC;
778 else
779 new_state = SELECT_OPERATION_SYNC;
780 break;
781 case SELECT_OPERATION_SYNC:
782 if (ldap_op == LDAP_REQ_ADD)
783 new_state = DO_ADD_SYNC;
784 else if (ldap_op == LDAP_REQ_DELETE)
785 new_state = DO_DELETE_SYNC;
786 else if (ldap_op == LDAP_REQ_MODIFY)
787 new_state = DO_MODIFY_SYNC;
788 break;
789 case SELECT_OPERATION_ASYNC:
790 if (ldap_op == LDAP_REQ_ADD)
791 new_state = DO_ADD_ASYNC;
792 else if (ldap_op == LDAP_REQ_DELETE)
793 new_state = DO_DELETE_ASYNC;
794 else if (ldap_op == LDAP_REQ_MODIFY)
795 new_state = DO_MODIFY_ASYNC;
796 break;
797 case DO_ADD_SYNC:
798 rc = ldap_add_ext_s(conp->ld, target_dn,
799 mods, NULL, NULL);
800 new_state = GET_RESULT_SYNC;
801 break;
802 case DO_DELETE_SYNC:
803 rc = ldap_delete_ext_s(conp->ld, target_dn,
804 NULL, NULL);
805 new_state = GET_RESULT_SYNC;
806 break;
807 case DO_MODIFY_SYNC:
808 rc = ldap_modify_ext_s(conp->ld, target_dn,
809 mods, NULL, NULL);
810 new_state = GET_RESULT_SYNC;
811 break;
812 case DO_ADD_ASYNC:
813 rc = ldap_add_ext(conp->ld, target_dn,
814 mods, NULL, NULL, &msgid);
815 new_state = GET_RESULT_ASYNC;
816 break;
817 case DO_DELETE_ASYNC:
818 rc = ldap_delete_ext(conp->ld, target_dn,
819 NULL, NULL, &msgid);
820 new_state = GET_RESULT_ASYNC;
821 break;
822 case DO_MODIFY_ASYNC:
823 rc = ldap_modify_ext(conp->ld, target_dn,
824 mods, NULL, NULL, &msgid);
825 new_state = GET_RESULT_ASYNC;
826 break;
827 case GET_RESULT_SYNC:
828 if (rc != LDAP_SUCCESS) {
829 Errno = rc;
830 (void) ldap_get_lderrno(conp->ld,
831 NULL, &errmsg);
834 * No need to deal with the error message if
835 * it's an empty string.
837 if (errmsg != NULL && *errmsg == '\0')
838 errmsg = NULL;
840 if (errmsg != NULL) {
842 * ldap_get_lderrno does not expect
843 * errmsg to be freed after use, while
844 * ldap_parse_result below does, so set
845 * a flag to indicate source.
847 from_get_lderrno = B_TRUE;
850 new_state = W_LDAP_ERROR;
851 } else {
852 return_rc = NS_LDAP_SUCCESS;
853 new_state = W_EXIT;
855 break;
856 case GET_RESULT_ASYNC:
857 rc = ldap_result(conp->ld, msgid, 1,
858 (struct timeval *)NULL, &res);
859 /* if no server response, set Errno */
860 if (rc == -1) {
861 (void) ldap_get_option(conp->ld,
862 LDAP_OPT_ERROR_NUMBER, &Errno);
863 new_state = W_LDAP_ERROR;
864 break;
866 if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY ||
867 rc == LDAP_RES_DELETE) {
868 new_state = PARSE_RESULT;
869 break;
870 } else {
871 return_rc = rc;
872 new_state = W_ERROR;
874 break;
875 case PARSE_RESULT:
877 * need Errno, referrals, error msg,
878 * and the last "1" is to free
879 * the result (res)
881 rc = ldap_parse_result(conp->ld, res, &Errno,
882 NULL, &errmsg, &referrals, NULL, 1);
884 * free errmsg if it is an empty string
886 if (errmsg && *errmsg == '\0') {
887 ldap_memfree(errmsg);
888 errmsg = NULL;
891 * If we received referral data, process
892 * it if:
893 * - we are configured to follow referrals
894 * - and not already in referral mode (to keep
895 * consistency with search_state_machine()
896 * which follows 1 level of referrals only;
897 * see proc_result_referrals() and
898 * proc_search_references().
900 if (Errno == LDAP_REFERRAL && followRef && !ref_list) {
901 for (i = 0; referrals[i] != NULL; i++) {
902 /* add to referral list */
903 rc = __s_api_addRefInfo(&ref_list,
904 referrals[i], NULL, NULL, NULL,
905 conp->ld);
906 if (rc != NS_LDAP_SUCCESS) {
907 __s_api_deleteRefInfo(ref_list);
908 ref_list = NULL;
909 break;
912 ldap_value_free(referrals);
913 if (ref_list == NULL) {
914 if (rc != NS_LDAP_MEMORY)
915 rc = NS_LDAP_INTERNAL;
916 return_rc = rc;
917 new_state = W_ERROR;
918 } else {
919 new_state = GET_REFERRAL_CONNECTION;
920 current_ref = ref_list;
922 if (errmsg) {
923 ldap_memfree(errmsg);
924 errmsg = NULL;
926 break;
928 if (Errno != LDAP_SUCCESS) {
929 new_state = W_LDAP_ERROR;
930 } else {
931 return_rc = NS_LDAP_SUCCESS;
932 new_state = W_EXIT;
934 break;
935 case GET_REFERRAL_CONNECTION:
937 * since we are starting over,
938 * discard the old error info
940 return_rc = NS_LDAP_SUCCESS;
941 if (*errorp)
942 (void) __ns_ldap_freeError(errorp);
943 if (connectionId > -1)
944 DropConnection(connectionId, NS_LDAP_NEW_CONN);
946 /* set it up to use a referral connection */
947 if (conn_user != NULL) {
949 * If an MT connection is being used,
950 * return it to the pool.
952 if (conn_user->conn_mt != NULL)
953 __s_api_conn_mt_return(conn_user);
955 conn_user->referral = B_TRUE;
957 rc = __s_api_getConnection(current_ref->refHost,
958 0, cred, &connectionId, &conp, errorp,
959 do_not_fail_if_new_pwd_reqd,
960 nopasswd_acct_mgmt, conn_user);
963 * If password control attached
964 * in errorp,
965 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
966 * free the error structure (we do not need
967 * the password management info).
968 * Reset rc to NS_LDAP_SUCCESS.
970 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
971 (void) __ns_ldap_freeError(errorp);
972 *errorp = NULL;
973 rc = NS_LDAP_SUCCESS;
976 if (rc != NS_LDAP_SUCCESS) {
977 return_rc = rc;
979 * If current referral is not
980 * available for some reason,
981 * try next referral in the list.
982 * Get LDAP error code from errorp.
984 if (*errorp != NULL) {
985 ns_write_state_t get_ref =
986 GET_REFERRAL_CONNECTION;
988 ldap_error = (*errorp)->status;
989 if (ldap_error == LDAP_BUSY ||
990 ldap_error == LDAP_UNAVAILABLE ||
991 ldap_error ==
992 LDAP_UNWILLING_TO_PERFORM ||
993 ldap_error == LDAP_CONNECT_ERROR ||
994 ldap_error == LDAP_SERVER_DOWN) {
995 current_ref = current_ref->next;
996 if (current_ref == NULL) {
997 /* no more referral to follow */
998 new_state = W_ERROR;
999 } else
1000 new_state = get_ref;
1002 * free errorp before going to
1003 * next referral
1005 (void) __ns_ldap_freeError(
1006 errorp);
1007 *errorp = NULL;
1008 break;
1011 * free errorp before going to W_ERROR
1013 (void) __ns_ldap_freeError(errorp);
1014 *errorp = NULL;
1016 /* else, exit */
1017 __s_api_deleteRefInfo(ref_list);
1018 ref_list = NULL;
1019 new_state = W_ERROR;
1020 if (conn_user != NULL)
1021 conn_user->referral = B_FALSE;
1022 break;
1024 /* target DN may changed due to referrals */
1025 if (current_ref->refDN) {
1026 if (target_dn && target_dn_allocated) {
1027 free(target_dn);
1028 target_dn = NULL;
1029 target_dn_allocated = FALSE;
1031 target_dn = current_ref->refDN;
1033 new_state = SELECT_OPERATION_SYNC;
1034 break;
1035 case W_LDAP_ERROR:
1037 * map error code and error message
1038 * to password status if necessary.
1039 * This is to see if password updates
1040 * failed due to password policy or
1041 * password syntax checking.
1043 if (errmsg) {
1045 * check if server supports
1046 * password management
1048 passwd_mgmt =
1049 __s_api_contain_passwd_control_oid(
1050 conp->controls);
1051 if (passwd_mgmt)
1052 pwd_status =
1053 __s_api_set_passwd_status(
1054 Errno, errmsg);
1056 * free only if not returned by ldap_get_lderrno
1058 if (!from_get_lderrno)
1059 ldap_memfree(errmsg);
1060 errmsg = NULL;
1061 from_get_lderrno = B_FALSE;
1064 (void) snprintf(errstr, sizeof (errstr),
1065 "%s", ldap_err2string(Errno));
1066 err = strdup(errstr);
1067 if (pwd_status != NS_PASSWD_GOOD) {
1068 MKERROR_PWD_MGMT(*errorp, Errno, err,
1069 pwd_status, 0, NULL);
1070 } else {
1071 MKERROR(LOG_INFO, *errorp, Errno, err, NULL);
1073 if (conn_user != NULL &&
1074 (Errno == LDAP_SERVER_DOWN ||
1075 Errno == LDAP_CONNECT_ERROR)) {
1076 __s_api_conn_mt_close(conn_user, Errno, errorp);
1078 return_rc = NS_LDAP_INTERNAL;
1079 new_state = W_EXIT;
1080 break;
1081 case W_ERROR:
1082 default:
1083 (void) sprintf(errstr,
1084 gettext("Internal write State machine exit"
1085 " (state = %d, rc = %d)."),
1086 err_state, return_rc);
1087 err = strdup(errstr);
1088 MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL);
1089 new_state = W_EXIT;
1090 break;
1093 if (new_state == W_ERROR)
1094 err_state = state;
1096 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
1097 __s_api_conn_mt_close(conn_user, 0, NULL);
1098 new_state = W_EXIT;
1101 state = new_state;
1105 * should never be here, the next line is to eliminating
1106 * lint message
1108 return (NS_LDAP_INTERNAL);
1112 /*ARGSUSED*/
1114 __ns_ldap_addAttr(
1115 const char *service,
1116 const char *dn,
1117 const ns_ldap_attr_t * const *attr,
1118 const ns_cred_t *cred,
1119 const int flags,
1120 ns_ldap_error_t ** errorp)
1122 LDAPMod **mods;
1123 int rc = 0;
1125 #ifdef DEBUG
1126 (void) fprintf(stderr, "__ns_ldap_addAttr START\n");
1127 #endif
1128 *errorp = NULL;
1130 /* Sanity check */
1131 if ((attr == NULL) || (*attr == NULL) ||
1132 (dn == NULL) || (cred == NULL))
1133 return (NS_LDAP_INVALID_PARAM);
1135 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1136 if (mods == NULL) {
1137 return (NS_LDAP_MEMORY);
1140 rc = write_state_machine(LDAP_REQ_MODIFY,
1141 (char *)dn, mods, cred, flags, errorp);
1142 freeModList(mods);
1144 return (rc);
1148 /*ARGSUSED*/
1150 __ns_ldap_delAttr(
1151 const char *service,
1152 const char *dn,
1153 const ns_ldap_attr_t * const *attr,
1154 const ns_cred_t *cred,
1155 const int flags,
1156 ns_ldap_error_t ** errorp)
1158 LDAPMod **mods;
1159 int rc = 0;
1161 #ifdef DEBUG
1162 (void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1163 #endif
1164 *errorp = NULL;
1166 /* Sanity check */
1167 if ((attr == NULL) || (*attr == NULL) ||
1168 (dn == NULL) || (cred == NULL))
1169 return (NS_LDAP_INVALID_PARAM);
1171 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1172 if (mods == NULL) {
1173 return (NS_LDAP_MEMORY);
1176 rc = write_state_machine(LDAP_REQ_MODIFY,
1177 (char *)dn, mods, cred, flags, errorp);
1179 freeModList(mods);
1180 return (rc);
1183 /* Retrieve the admin bind password from the configuration, if allowed. */
1184 static int
1185 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
1187 void **paramVal = NULL;
1188 int rc, ldaprc;
1189 char *modparamVal = NULL;
1192 * For GSSAPI/Kerberos, host credential is used, no need to get
1193 * admin bind password
1195 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
1196 return (NS_LDAP_SUCCESS);
1199 * Retrieve admin bind password.
1200 * The admin bind password is available
1201 * only in the ldap_cachemgr process as
1202 * they are not exposed outside of that
1203 * process.
1205 paramVal = NULL;
1206 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1207 &paramVal, errorp)) != NS_LDAP_SUCCESS)
1208 return (ldaprc);
1209 if (paramVal == NULL || *paramVal == NULL) {
1210 rc = NS_LDAP_CONFIG;
1211 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
1212 gettext("Admin bind password not configured"));
1213 if (*errorp == NULL)
1214 rc = NS_LDAP_MEMORY;
1215 return (rc);
1217 modparamVal = dvalue((char *)*paramVal);
1218 (void) memset(*paramVal, 0, strlen((char *)*paramVal));
1219 (void) __ns_ldap_freeParam(&paramVal);
1220 if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
1221 if (modparamVal != NULL)
1222 free(modparamVal);
1223 rc = NS_LDAP_CONFIG;
1224 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
1225 gettext("bind password not valid"));
1226 if (*errorp == NULL)
1227 rc = NS_LDAP_MEMORY;
1228 return (rc);
1231 cred->cred.unix_cred.passwd = modparamVal;
1232 return (NS_LDAP_SUCCESS);
1235 boolean_t
1236 __ns_ldap_is_shadow_update_enabled(void)
1238 int **enable_shadow = NULL;
1239 ns_ldap_error_t *errorp = NULL;
1241 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1242 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1243 if (errorp)
1244 (void) __ns_ldap_freeError(&errorp);
1245 return (B_FALSE);
1247 if ((enable_shadow != NULL && *enable_shadow != NULL) &&
1248 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
1249 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1250 return (B_TRUE);
1252 if (enable_shadow != NULL)
1253 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1254 return (B_FALSE);
1258 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
1259 * on the LDAP server. 'service' indicates the type of database entries
1260 * to modify. When the Native LDAP client is configured with 'shadow update
1261 * enabled', Shadowshadow(4) entries can only be modified by privileged users.
1262 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
1263 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
1264 * for performing the LDAP modify operation. ldap_cachemgr would call
1265 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
1266 * to identify itself, so that admin credential would be obtained and
1267 * the actual LDAP modify operation be done.
1269 /*ARGSUSED*/
1271 __ns_ldap_repAttr(
1272 const char *service,
1273 const char *dn,
1274 const ns_ldap_attr_t * const *attr,
1275 const ns_cred_t *cred,
1276 const int flags,
1277 ns_ldap_error_t ** errorp)
1279 LDAPMod **mods;
1280 int rc = 0;
1281 boolean_t priv;
1282 boolean_t shadow_update_enabled = B_FALSE;
1284 #ifdef DEBUG
1285 (void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1286 #endif
1287 *errorp = NULL;
1289 /* Sanity check */
1290 if (attr == NULL || *attr == NULL || dn == NULL)
1291 return (NS_LDAP_INVALID_PARAM);
1293 /* Privileged shadow modify? */
1294 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
1295 strcmp(service, "shadow") == 0) {
1297 /* Shadow update enabled ? If not, error out */
1298 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
1299 if (!shadow_update_enabled) {
1300 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
1301 gettext("Shadow Update is not enabled"));
1302 return (NS_LDAP_CONFIG);
1305 /* privileged shadow modify requires euid 0 or all zone privs */
1306 priv = (geteuid() == 0);
1307 if (!priv) {
1308 priv_set_t *ps = priv_allocset(); /* caller */
1309 priv_set_t *zs; /* zone */
1311 (void) getppriv(PRIV_EFFECTIVE, ps);
1312 zs = priv_str_to_set("zone", ",", NULL);
1313 priv = priv_isequalset(ps, zs);
1314 priv_freeset(ps);
1315 priv_freeset(zs);
1317 if (!priv)
1318 return (NS_LDAP_OP_FAILED);
1320 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
1321 return (rc);
1324 if (cred == NULL)
1325 return (NS_LDAP_INVALID_PARAM);
1328 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
1329 * ldap_cachemgr. We need to get the admin cred to do work.
1330 * If the caller is not ldap_cachemgr, but use the service
1331 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
1332 * as the admin cred is not available to the caller.
1334 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
1335 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
1336 NS_LDAP_SUCCESS)
1337 return (rc);
1340 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1341 if (mods == NULL)
1342 return (NS_LDAP_MEMORY);
1344 rc = write_state_machine(LDAP_REQ_MODIFY,
1345 (char *)dn, mods, cred, flags, errorp);
1347 freeModList(mods);
1348 return (rc);
1351 /*ARGSUSED*/
1353 __ns_ldap_addEntry(
1354 const char *service,
1355 const char *dn,
1356 const ns_ldap_entry_t *entry,
1357 const ns_cred_t *cred,
1358 const int flags,
1359 ns_ldap_error_t ** errorp)
1361 char *new_dn = NULL;
1362 LDAPMod **mods = NULL;
1363 const ns_ldap_attr_t * const *attr;
1364 int nAttr = 0;
1365 int rc = 0;
1367 #ifdef DEBUG
1368 (void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1369 #endif
1371 if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1372 return (NS_LDAP_INVALID_PARAM);
1373 *errorp = NULL;
1375 /* Construct array of LDAPMod representing attributes of new entry. */
1377 nAttr = entry->attr_count;
1378 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1379 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1380 nAttr, flags);
1381 if (mods == NULL) {
1382 return (NS_LDAP_MEMORY);
1385 rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1386 if (rc != NS_LDAP_SUCCESS) {
1387 freeModList(mods);
1388 return (rc);
1391 rc = write_state_machine(LDAP_REQ_ADD,
1392 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1394 if (new_dn)
1395 free(new_dn);
1396 freeModList(mods);
1397 return (rc);
1401 /*ARGSUSED*/
1403 __ns_ldap_delEntry(
1404 const char *service,
1405 const char *dn,
1406 const ns_cred_t *cred,
1407 const int flags,
1408 ns_ldap_error_t ** errorp)
1410 int rc;
1412 #ifdef DEBUG
1413 (void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1414 #endif
1415 if ((dn == NULL) || (cred == NULL))
1416 return (NS_LDAP_INVALID_PARAM);
1418 *errorp = NULL;
1420 rc = write_state_machine(LDAP_REQ_DELETE,
1421 (char *)dn, NULL, cred, flags, errorp);
1423 return (rc);
1427 * Add Typed Entry Helper routines
1431 * Add Typed Entry Conversion routines
1434 static int
1435 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1437 ns_ldap_attr_t *a;
1438 char *v;
1440 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1441 if (a == NULL)
1442 return (NS_LDAP_MEMORY);
1443 a->attrname = strdup(attrname);
1444 if (a->attrname == NULL)
1445 return (NS_LDAP_MEMORY);
1446 a->attrvalue = (char **)calloc(1, sizeof (char **));
1447 if (a->attrvalue == NULL)
1448 return (NS_LDAP_MEMORY);
1449 a->value_count = 1;
1450 a->attrvalue[0] = NULL;
1451 v = strdup(value);
1452 if (v == NULL)
1453 return (NS_LDAP_MEMORY);
1454 a->attrvalue[0] = v;
1455 e->attr_pair[e->attr_count] = a;
1456 e->attr_count++;
1457 return (NS_LDAP_SUCCESS);
1460 static int
1461 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1463 ns_ldap_attr_t *a;
1464 char *v;
1465 char **av;
1466 int i, j;
1468 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1469 if (a == NULL)
1470 return (NS_LDAP_MEMORY);
1471 a->attrname = strdup(attrname);
1472 if (a->attrname == NULL)
1473 return (NS_LDAP_MEMORY);
1475 for (i = 0, av = argv; *av != NULL; av++, i++)
1478 a->attrvalue = (char **)calloc(i, sizeof (char *));
1480 if (a->attrvalue == NULL)
1481 return (NS_LDAP_MEMORY);
1483 a->value_count = i;
1484 for (j = 0; j < i; j++) {
1485 v = strdup(argv[j]);
1486 if (v == NULL)
1487 return (NS_LDAP_MEMORY);
1488 a->attrvalue[j] = v;
1490 e->attr_pair[e->attr_count] = a;
1491 e->attr_count++;
1492 return (NS_LDAP_SUCCESS);
1495 static ns_ldap_entry_t *
1496 __s_mk_entry(char **objclass, int max_attr)
1498 ns_ldap_entry_t *e;
1499 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1500 if (e == NULL)
1501 return (NULL);
1502 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1503 e->attr_pair = (ns_ldap_attr_t **)
1504 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1505 if (e->attr_pair == NULL) {
1506 free(e);
1507 return (NULL);
1509 e->attr_count = 0;
1510 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1511 free(e->attr_pair);
1512 free(e);
1513 return (NULL);
1515 return (e);
1520 * Conversion: passwd
1521 * Input format: struct passwd
1522 * Exported objectclass: posixAccount
1524 static int
1525 __s_cvt_passwd(const void *data, char **rdn,
1526 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1528 ns_ldap_entry_t *e;
1529 int rc;
1530 char trdn[RDNSIZE];
1531 /* routine specific */
1532 struct passwd *ptr;
1533 int max_attr = 9;
1534 char ibuf[10];
1535 static char *oclist[] = {
1536 "posixAccount",
1537 "shadowAccount",
1538 "account",
1539 "top",
1540 NULL
1543 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1544 return (NS_LDAP_OP_FAILED);
1545 *entry = e = __s_mk_entry(oclist, max_attr);
1546 if (e == NULL)
1547 return (NS_LDAP_MEMORY);
1549 /* Convert the structure */
1550 ptr = (struct passwd *)data;
1552 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
1553 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
1554 __ns_ldap_freeEntry(e);
1555 *entry = NULL;
1556 return (NS_LDAP_INVALID_PARAM);
1559 /* Create an appropriate rdn */
1560 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1561 *rdn = strdup(trdn);
1562 if (*rdn == NULL) {
1563 __ns_ldap_freeEntry(e);
1564 *entry = NULL;
1565 return (NS_LDAP_MEMORY);
1568 /* Error check the data and add the attributes */
1569 rc = __s_add_attr(e, "uid", ptr->pw_name);
1570 if (rc != NS_LDAP_SUCCESS) {
1571 __s_cvt_freeEntryRdn(entry, rdn);
1572 return (rc);
1574 rc = __s_add_attr(e, "cn", ptr->pw_name);
1575 if (rc != NS_LDAP_SUCCESS) {
1576 __s_cvt_freeEntryRdn(entry, rdn);
1577 return (rc);
1580 if (ptr->pw_passwd != NULL &&
1581 ptr->pw_passwd[0] != '\0') {
1582 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1583 if (rc != NS_LDAP_SUCCESS) {
1584 __s_cvt_freeEntryRdn(entry, rdn);
1585 return (rc);
1589 (void) sprintf(ibuf, "%u", ptr->pw_uid);
1590 rc = __s_add_attr(e, "uidNumber", ibuf);
1591 if (rc != NS_LDAP_SUCCESS) {
1592 __s_cvt_freeEntryRdn(entry, rdn);
1593 return (rc);
1596 (void) sprintf(ibuf, "%u", ptr->pw_gid);
1597 rc = __s_add_attr(e, "gidNumber", ibuf);
1598 if (rc != NS_LDAP_SUCCESS) {
1599 __s_cvt_freeEntryRdn(entry, rdn);
1600 return (rc);
1602 if (ptr->pw_gecos != NULL &&
1603 ptr->pw_gecos[0] != '\0') {
1604 rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1605 if (rc != NS_LDAP_SUCCESS) {
1606 __s_cvt_freeEntryRdn(entry, rdn);
1607 return (rc);
1611 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1612 if (rc != NS_LDAP_SUCCESS) {
1613 __s_cvt_freeEntryRdn(entry, rdn);
1614 return (rc);
1616 if (ptr->pw_shell != NULL &&
1617 ptr->pw_shell[0] != '\0') {
1618 rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1619 if (rc != NS_LDAP_SUCCESS) {
1620 __s_cvt_freeEntryRdn(entry, rdn);
1621 return (rc);
1625 return (NS_LDAP_SUCCESS);
1629 * escape_str function escapes special characters in str and
1630 * copies to escstr string.
1632 * return 0 for successful
1633 * 1 for fail
1635 static int escape_str(char *escstr, char *str)
1637 int index = 0;
1639 while ((*str != '\0') && (index < (RDNSIZE - 1))) {
1640 if (*str == '+' || *str == ';' || *str == '>' ||
1641 *str == '<' || *str == ',' || *str == '"' ||
1642 *str == '\\' || *str == '=' ||
1643 (*str == '#' && index == 0)) {
1644 *escstr++ = '\\';
1645 *escstr++ = *str++;
1646 index += 2;
1647 } else {
1648 *escstr++ = *str++;
1649 index++;
1653 if (*str == '\0') {
1654 *escstr = '\0';
1655 return (0);
1656 } else {
1657 return (1);
1662 * Conversion: project
1663 * Input format: struct project
1664 * Exported objectclass: SolarisProject
1666 static int
1667 __s_cvt_project(const void *data, char **rdn,
1668 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1670 ns_ldap_entry_t *e;
1671 int rc;
1672 char trdn[RDNSIZE];
1674 /* routine specific */
1675 struct project *ptr;
1676 int max_attr = 9;
1677 char ibuf[11];
1678 static char *oclist[] = {
1679 "SolarisProject",
1680 "top",
1681 NULL
1684 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1685 return (NS_LDAP_OP_FAILED);
1687 *entry = e = __s_mk_entry(oclist, max_attr);
1688 if (e == NULL)
1689 return (NS_LDAP_MEMORY);
1691 /* Convert the structure */
1692 ptr = (struct project *)data;
1694 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
1695 __ns_ldap_freeEntry(e);
1696 *entry = NULL;
1697 return (NS_LDAP_INVALID_PARAM);
1700 /* Create an appropriate rdn */
1701 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
1702 *rdn = strdup(trdn);
1703 if (*rdn == NULL) {
1704 __ns_ldap_freeEntry(e);
1705 *entry = NULL;
1706 return (NS_LDAP_MEMORY);
1709 /* Error check the data and add the attributes */
1711 /* Project name */
1712 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
1713 if (rc != NS_LDAP_SUCCESS) {
1714 __s_cvt_freeEntryRdn(entry, rdn);
1715 return (rc);
1719 * Project ID:
1720 * ibuf is 11 chars big, which should be enough for string
1721 * representation of 32bit number + nul-car
1723 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
1724 __s_cvt_freeEntryRdn(entry, rdn);
1725 return (NS_LDAP_INVALID_PARAM);
1727 rc = __s_add_attr(e, "SolarisProjectID", ibuf);
1728 if (rc != NS_LDAP_SUCCESS) {
1729 __s_cvt_freeEntryRdn(entry, rdn);
1730 return (rc);
1733 /* Comment/Description */
1734 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
1735 rc = __s_add_attr(e, "description", ptr->pj_comment);
1736 if (rc != NS_LDAP_SUCCESS) {
1737 __s_cvt_freeEntryRdn(entry, rdn);
1738 return (rc);
1742 /* Attributes */
1743 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
1744 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
1745 if (rc != NS_LDAP_SUCCESS) {
1746 __s_cvt_freeEntryRdn(entry, rdn);
1747 return (rc);
1751 /* Users */
1752 if (ptr->pj_users != NULL) {
1753 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
1754 if (rc != NS_LDAP_SUCCESS) {
1755 __s_cvt_freeEntryRdn(entry, rdn);
1756 return (rc);
1760 /* Groups */
1761 if (ptr->pj_groups != NULL) {
1762 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
1763 if (rc != NS_LDAP_SUCCESS) {
1764 __s_cvt_freeEntryRdn(entry, rdn);
1765 return (rc);
1771 return (NS_LDAP_SUCCESS);
1774 * Conversion: shadow
1775 * Input format: struct shadow
1776 * Exported objectclass: shadowAccount
1778 static int
1779 __s_cvt_shadow(const void *data, char **rdn,
1780 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1782 ns_ldap_entry_t *e;
1783 int rc;
1784 char trdn[RDNSIZE];
1785 /* routine specific */
1786 struct spwd *ptr;
1787 int max_attr = 10;
1788 char ibuf[10];
1789 static char *oclist[] = {
1790 "posixAccount",
1791 "shadowAccount",
1792 "account",
1793 "top",
1794 NULL
1797 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1798 return (NS_LDAP_OP_FAILED);
1799 *entry = e = __s_mk_entry(oclist, max_attr);
1800 if (e == NULL)
1801 return (NS_LDAP_MEMORY);
1803 /* Convert the structure */
1804 ptr = (struct spwd *)data;
1806 if (ptr->sp_namp == NULL) {
1807 __ns_ldap_freeEntry(e);
1808 *entry = NULL;
1809 return (NS_LDAP_INVALID_PARAM);
1812 /* Create an appropriate rdn */
1813 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1814 *rdn = strdup(trdn);
1815 if (*rdn == NULL) {
1816 __ns_ldap_freeEntry(e);
1817 *entry = NULL;
1818 return (NS_LDAP_MEMORY);
1821 /* Error check the data and add the attributes */
1822 rc = __s_add_attr(e, "uid", ptr->sp_namp);
1823 if (rc != NS_LDAP_SUCCESS) {
1824 __s_cvt_freeEntryRdn(entry, rdn);
1825 return (rc);
1828 if (ptr->sp_pwdp == NULL) {
1829 __s_cvt_freeEntryRdn(entry, rdn);
1830 return (NS_LDAP_INVALID_PARAM);
1831 } else {
1832 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1833 if (rc != NS_LDAP_SUCCESS) {
1834 __s_cvt_freeEntryRdn(entry, rdn);
1835 return (rc);
1838 if (ptr->sp_lstchg >= 0) {
1839 (void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1840 rc = __s_add_attr(e, "shadowLastChange", ibuf);
1841 if (rc != NS_LDAP_SUCCESS) {
1842 __s_cvt_freeEntryRdn(entry, rdn);
1843 return (rc);
1846 if (ptr->sp_min >= 0) {
1847 (void) sprintf(ibuf, "%d", ptr->sp_min);
1848 rc = __s_add_attr(e, "shadowMin", ibuf);
1849 if (rc != NS_LDAP_SUCCESS) {
1850 __s_cvt_freeEntryRdn(entry, rdn);
1851 return (rc);
1854 if (ptr->sp_max >= 0) {
1855 (void) sprintf(ibuf, "%d", ptr->sp_max);
1856 rc = __s_add_attr(e, "shadowMax", ibuf);
1857 if (rc != NS_LDAP_SUCCESS) {
1858 __s_cvt_freeEntryRdn(entry, rdn);
1859 return (rc);
1862 if (ptr->sp_warn >= 0) {
1863 (void) sprintf(ibuf, "%d", ptr->sp_warn);
1864 rc = __s_add_attr(e, "shadowWarning", ibuf);
1865 if (rc != NS_LDAP_SUCCESS) {
1866 __s_cvt_freeEntryRdn(entry, rdn);
1867 return (rc);
1870 if (ptr->sp_inact >= 0) {
1871 (void) sprintf(ibuf, "%d", ptr->sp_inact);
1872 rc = __s_add_attr(e, "shadowInactive", ibuf);
1873 if (rc != NS_LDAP_SUCCESS) {
1874 __s_cvt_freeEntryRdn(entry, rdn);
1875 return (rc);
1878 if (ptr->sp_expire >= 0) {
1879 (void) sprintf(ibuf, "%d", ptr->sp_expire);
1880 rc = __s_add_attr(e, "shadowExpire", ibuf);
1881 if (rc != NS_LDAP_SUCCESS) {
1882 __s_cvt_freeEntryRdn(entry, rdn);
1883 return (rc);
1886 (void) sprintf(ibuf, "%d", ptr->sp_flag);
1887 rc = __s_add_attr(e, "shadowFlag", ibuf);
1888 if (rc != NS_LDAP_SUCCESS) {
1889 __s_cvt_freeEntryRdn(entry, rdn);
1890 return (rc);
1893 return (NS_LDAP_SUCCESS);
1898 * Conversion: group
1899 * Input format: struct group
1900 * Exported objectclass: posixGroup
1902 static int
1903 __s_cvt_group(const void *data, char **rdn,
1904 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1906 ns_ldap_entry_t *e;
1907 int rc;
1908 char trdn[RDNSIZE];
1909 /* routine specific */
1910 struct group *ptr;
1911 int i, j, k;
1912 char **nm, **lm;
1913 int max_attr = 4;
1914 char ibuf[10];
1915 static char *oclist[] = {
1916 "posixGroup",
1917 "top",
1918 NULL
1921 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1922 return (NS_LDAP_OP_FAILED);
1923 *entry = e = __s_mk_entry(oclist, max_attr);
1924 if (e == NULL)
1925 return (NS_LDAP_MEMORY);
1927 /* Convert the structure */
1928 ptr = (struct group *)data;
1930 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
1931 __ns_ldap_freeEntry(e);
1932 *entry = NULL;
1933 return (NS_LDAP_INVALID_PARAM);
1936 /* Create an appropriate rdn */
1937 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1938 *rdn = strdup(trdn);
1939 if (*rdn == NULL) {
1940 __ns_ldap_freeEntry(e);
1941 *entry = NULL;
1942 return (NS_LDAP_MEMORY);
1945 /* Error check the data and add the attributes */
1946 rc = __s_add_attr(e, "cn", ptr->gr_name);
1947 if (rc != NS_LDAP_SUCCESS) {
1948 __s_cvt_freeEntryRdn(entry, rdn);
1949 return (rc);
1952 (void) sprintf(ibuf, "%u", ptr->gr_gid);
1953 rc = __s_add_attr(e, "gidNumber", ibuf);
1954 if (rc != NS_LDAP_SUCCESS) {
1955 __s_cvt_freeEntryRdn(entry, rdn);
1956 return (rc);
1958 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1959 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1960 if (rc != NS_LDAP_SUCCESS) {
1961 __s_cvt_freeEntryRdn(entry, rdn);
1962 return (rc);
1966 if (ptr->gr_mem && ptr->gr_mem[0]) {
1967 lm = ptr->gr_mem;
1968 for (i = 0; *lm; i++, lm++)
1970 lm = ptr->gr_mem;
1971 nm = (char **)calloc(i+2, sizeof (char *));
1972 if (nm == NULL) {
1973 __s_cvt_freeEntryRdn(entry, rdn);
1974 return (NS_LDAP_MEMORY);
1976 for (j = 0; j < i; j++) {
1977 nm[j] = strdup(lm[j]);
1978 if (nm[j] == NULL) {
1979 for (k = 0; k < j; k++)
1980 free(nm[k]);
1981 free(nm);
1982 __s_cvt_freeEntryRdn(entry, rdn);
1983 return (NS_LDAP_MEMORY);
1986 rc = __s_add_attrlist(e, "memberUid", nm);
1987 for (j = 0; j < i; j++) {
1988 free(nm[j]);
1990 free(nm);
1991 nm = NULL;
1992 if (rc != NS_LDAP_SUCCESS) {
1993 __s_cvt_freeEntryRdn(entry, rdn);
1994 return (rc);
1998 return (NS_LDAP_SUCCESS);
2002 * Conversion: hosts
2003 * Input format: struct hostent
2004 * Exported objectclass: ipHost
2006 static int
2007 __s_cvt_hosts(const void *data, char **rdn,
2008 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2010 ns_ldap_entry_t *e;
2011 int rc;
2012 char trdn[RDNSIZE];
2013 /* routine specific */
2014 struct hostent *ptr;
2015 int max_attr = 6;
2016 int i, j, k;
2017 char **nm, **lm;
2018 static char *oclist[] = {
2019 "ipHost",
2020 "device",
2021 "top",
2022 NULL
2025 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2026 return (NS_LDAP_OP_FAILED);
2027 *entry = e = __s_mk_entry(oclist, max_attr);
2028 if (e == NULL)
2029 return (NS_LDAP_MEMORY);
2031 /* Convert the structure */
2032 ptr = (struct hostent *)data;
2034 if (ptr->h_name == NULL ||
2035 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == NULL) {
2036 __ns_ldap_freeEntry(e);
2037 *entry = NULL;
2038 return (NS_LDAP_INVALID_PARAM);
2041 /* Create an appropriate rdn */
2042 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
2043 ptr->h_name, ptr->h_addr_list[0]);
2044 *rdn = strdup(trdn);
2045 if (*rdn == NULL) {
2046 __ns_ldap_freeEntry(e);
2047 *entry = NULL;
2048 return (NS_LDAP_MEMORY);
2051 /* Error check the data and add the attributes */
2052 if (ptr->h_aliases && ptr->h_aliases[0]) {
2053 lm = ptr->h_aliases;
2055 * If there is a description, 'i' will contain
2056 * the index of the description in the aliases list
2058 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
2060 lm = ptr->h_aliases;
2061 nm = (char **)calloc(i+2, sizeof (char *));
2062 if (nm == NULL) {
2063 __s_cvt_freeEntryRdn(entry, rdn);
2064 return (NS_LDAP_MEMORY);
2066 nm[0] = ptr->h_name;
2067 for (j = 0; j < i; j++)
2068 nm[j+1] = ptr->h_aliases[j];
2070 rc = __s_add_attrlist(e, "cn", nm);
2072 if (rc != NS_LDAP_SUCCESS) {
2073 __s_cvt_freeEntryRdn(entry, rdn);
2074 free(nm);
2075 return (rc);
2078 if (lm[i] && lm[i][0] == '#') {
2079 nm[0] = &(lm[i][1]);
2080 nm[1] = NULL;
2081 rc = __s_add_attrlist(e, "description", nm);
2083 free(nm);
2084 nm = NULL;
2085 if (rc != NS_LDAP_SUCCESS) {
2086 __s_cvt_freeEntryRdn(entry, rdn);
2087 return (rc);
2089 } else {
2090 rc = __s_add_attr(e, "cn", ptr->h_name);
2091 if (rc != NS_LDAP_SUCCESS) {
2092 __s_cvt_freeEntryRdn(entry, rdn);
2093 return (rc);
2097 if (ptr->h_addr_list && ptr->h_addr_list[0]) {
2098 lm = ptr->h_addr_list;
2099 for (i = 0; *lm; i++, lm++)
2101 lm = ptr->h_addr_list;
2102 nm = (char **)calloc(i+2, sizeof (char *));
2103 if (nm == NULL) {
2104 __s_cvt_freeEntryRdn(entry, rdn);
2105 return (NS_LDAP_MEMORY);
2107 for (j = 0; j < i; j++) {
2108 nm[j] = strdup(lm[j]);
2109 if (nm[j] == NULL) {
2110 for (k = 0; k < j; k++)
2111 free(nm[k]);
2112 free(nm);
2113 __s_cvt_freeEntryRdn(entry, rdn);
2114 return (NS_LDAP_MEMORY);
2117 rc = __s_add_attrlist(e, "ipHostNumber", nm);
2118 for (j = 0; j < i; j++) {
2119 free(nm[j]);
2121 free(nm);
2122 nm = NULL;
2123 if (rc != NS_LDAP_SUCCESS) {
2124 __s_cvt_freeEntryRdn(entry, rdn);
2125 return (rc);
2127 } else {
2128 __s_cvt_freeEntryRdn(entry, rdn);
2129 return (NS_LDAP_INVALID_PARAM);
2132 return (NS_LDAP_SUCCESS);
2136 * Conversion: rpc
2137 * Input format: struct rpcent
2138 * Exported objectclass: oncRpc
2140 static int
2141 __s_cvt_rpc(const void *data, char **rdn,
2142 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2144 ns_ldap_entry_t *e;
2145 int rc;
2146 char trdn[RDNSIZE];
2147 /* routine specific */
2148 struct rpcent *ptr;
2149 int max_attr = 3;
2150 int i, j;
2151 char **nm;
2152 char ibuf[10];
2153 static char *oclist[] = {
2154 "oncRpc",
2155 "top",
2156 NULL
2159 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2160 return (NS_LDAP_OP_FAILED);
2161 *entry = e = __s_mk_entry(oclist, max_attr);
2162 if (e == NULL)
2163 return (NS_LDAP_MEMORY);
2165 /* Convert the structure */
2166 ptr = (struct rpcent *)data;
2168 if (ptr->r_name == NULL || ptr->r_number < 0) {
2169 __ns_ldap_freeEntry(e);
2170 *entry = NULL;
2171 return (NS_LDAP_INVALID_PARAM);
2174 /* Create an appropriate rdn */
2175 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
2176 *rdn = strdup(trdn);
2177 if (*rdn == NULL) {
2178 __ns_ldap_freeEntry(e);
2179 *entry = NULL;
2180 return (NS_LDAP_MEMORY);
2183 /* Error check the data and add the attributes */
2184 if (ptr->r_aliases && ptr->r_aliases[0]) {
2185 nm = ptr->r_aliases;
2186 for (i = 0; *nm; i++, nm++)
2188 nm = (char **)calloc(i+2, sizeof (char *));
2189 if (nm == NULL) {
2190 __s_cvt_freeEntryRdn(entry, rdn);
2191 return (NS_LDAP_MEMORY);
2193 nm[0] = ptr->r_name;
2194 for (j = 0; j < i; j++)
2195 nm[j+1] = ptr->r_aliases[j];
2197 rc = __s_add_attrlist(e, "cn", nm);
2198 free(nm);
2199 nm = NULL;
2200 if (rc != NS_LDAP_SUCCESS) {
2201 __s_cvt_freeEntryRdn(entry, rdn);
2202 return (rc);
2204 } else {
2205 rc = __s_add_attr(e, "cn", ptr->r_name);
2206 if (rc != NS_LDAP_SUCCESS) {
2207 __s_cvt_freeEntryRdn(entry, rdn);
2208 return (rc);
2212 if (ptr->r_number >= 0) {
2213 (void) sprintf(ibuf, "%d", ptr->r_number);
2214 rc = __s_add_attr(e, "oncRpcNumber", ibuf);
2215 if (rc != NS_LDAP_SUCCESS) {
2216 __s_cvt_freeEntryRdn(entry, rdn);
2217 return (rc);
2221 return (NS_LDAP_SUCCESS);
2226 * Conversion: protocols
2227 * Input format: struct protoent
2228 * Exported objectclass: ipProtocol
2230 static int
2231 __s_cvt_protocols(const void *data, char **rdn,
2232 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2234 ns_ldap_entry_t *e;
2235 int rc;
2236 char trdn[RDNSIZE];
2237 /* routine specific */
2238 struct protoent *ptr;
2239 int max_attr = 3;
2240 int i, j;
2241 char ibuf[10];
2242 char **nm;
2243 static char *oclist[] = {
2244 "ipProtocol",
2245 "top",
2246 NULL
2249 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2250 return (NS_LDAP_OP_FAILED);
2251 *entry = e = __s_mk_entry(oclist, max_attr);
2252 if (e == NULL)
2253 return (NS_LDAP_MEMORY);
2255 /* Convert the structure */
2256 ptr = (struct protoent *)data;
2258 if (ptr->p_name == NULL || ptr->p_proto < 0) {
2259 __ns_ldap_freeEntry(e);
2260 *entry = NULL;
2261 return (NS_LDAP_INVALID_PARAM);
2264 /* Create an appropriate rdn */
2265 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
2266 *rdn = strdup(trdn);
2267 if (*rdn == NULL) {
2268 __ns_ldap_freeEntry(e);
2269 *entry = NULL;
2270 return (NS_LDAP_MEMORY);
2273 /* Error check the data and add the attributes */
2274 if (ptr->p_aliases && ptr->p_aliases[0]) {
2275 nm = ptr->p_aliases;
2276 for (i = 0; *nm; i++, nm++)
2278 nm = (char **)calloc(i+2, sizeof (char *));
2279 if (nm == NULL) {
2280 __s_cvt_freeEntryRdn(entry, rdn);
2281 return (NS_LDAP_MEMORY);
2283 nm[0] = ptr->p_name;
2284 for (j = 0; j < i; j++)
2285 nm[j+1] = ptr->p_aliases[j];
2287 rc = __s_add_attrlist(e, "cn", nm);
2288 free(nm);
2289 nm = NULL;
2290 if (rc != NS_LDAP_SUCCESS) {
2291 __s_cvt_freeEntryRdn(entry, rdn);
2292 return (rc);
2294 } else {
2295 rc = __s_add_attr(e, "cn", ptr->p_name);
2296 if (rc != NS_LDAP_SUCCESS) {
2297 __s_cvt_freeEntryRdn(entry, rdn);
2298 return (rc);
2302 (void) sprintf(ibuf, "%d", ptr->p_proto);
2303 rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
2304 if (rc != NS_LDAP_SUCCESS) {
2305 __s_cvt_freeEntryRdn(entry, rdn);
2306 return (rc);
2309 return (NS_LDAP_SUCCESS);
2314 * Conversion: services
2315 * Input format: struct servent
2316 * Exported objectclass: ipService
2318 static int
2319 __s_cvt_services(const void *data, char **rdn,
2320 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2322 ns_ldap_entry_t *e;
2323 int rc;
2324 char trdn[RDNSIZE];
2325 char esc_str[RDNSIZE];
2326 /* routine specific */
2327 struct servent *ptr;
2328 int max_attr = 4;
2329 int i, j;
2330 char ibuf[10];
2331 char **nm;
2332 static char *oclist[] = {
2333 "ipService",
2334 "top",
2335 NULL
2338 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2339 return (NS_LDAP_OP_FAILED);
2340 *entry = e = __s_mk_entry(oclist, max_attr);
2341 if (e == NULL)
2342 return (NS_LDAP_MEMORY);
2344 /* Convert the structure */
2345 ptr = (struct servent *)data;
2347 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == NULL) {
2348 __ns_ldap_freeEntry(e);
2349 *entry = NULL;
2350 return (NS_LDAP_INVALID_PARAM);
2354 * Escape special characters in service name.
2356 if (escape_str(esc_str, ptr->s_name) != 0) {
2357 __ns_ldap_freeEntry(e);
2358 *entry = NULL;
2359 return (NS_LDAP_INVALID_PARAM);
2362 /* Create an appropriate rdn */
2363 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
2364 esc_str, ptr->s_proto);
2366 *rdn = strdup(trdn);
2367 if (*rdn == NULL) {
2368 __ns_ldap_freeEntry(e);
2369 *entry = NULL;
2370 return (NS_LDAP_MEMORY);
2373 /* Error check the data and add the attributes */
2374 if (ptr->s_aliases && ptr->s_aliases[0]) {
2375 nm = ptr->s_aliases;
2376 for (i = 0; *nm; i++, nm++)
2378 nm = (char **)calloc(i+2, sizeof (char *));
2379 if (nm == NULL) {
2380 __s_cvt_freeEntryRdn(entry, rdn);
2381 return (NS_LDAP_MEMORY);
2383 nm[0] = ptr->s_name;
2384 for (j = 0; j < i; j++)
2385 nm[j+1] = ptr->s_aliases[j];
2387 rc = __s_add_attrlist(e, "cn", nm);
2388 free(nm);
2389 nm = NULL;
2390 if (rc != NS_LDAP_SUCCESS) {
2391 __s_cvt_freeEntryRdn(entry, rdn);
2392 return (rc);
2394 } else {
2395 rc = __s_add_attr(e, "cn", ptr->s_name);
2396 if (rc != NS_LDAP_SUCCESS) {
2397 __s_cvt_freeEntryRdn(entry, rdn);
2398 return (rc);
2402 (void) sprintf(ibuf, "%d", ptr->s_port);
2403 rc = __s_add_attr(e, "ipServicePort", ibuf);
2404 if (rc != NS_LDAP_SUCCESS) {
2405 __s_cvt_freeEntryRdn(entry, rdn);
2406 return (rc);
2408 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
2409 if (rc != NS_LDAP_SUCCESS) {
2410 __s_cvt_freeEntryRdn(entry, rdn);
2411 return (rc);
2414 return (NS_LDAP_SUCCESS);
2418 * Conversion: networks
2419 * Input format: struct netent
2420 * Exported objectclass: ipNetwork
2422 static int
2423 __s_cvt_networks(const void *data, char **rdn,
2424 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2426 ns_ldap_entry_t *e;
2427 int rc;
2428 char trdn[RDNSIZE];
2429 /* routine specific */
2430 struct netent *ptr;
2431 int max_attr = 4;
2432 int i, j;
2433 char cp[64];
2434 char **nm;
2435 static char *oclist[] = {
2436 "ipNetwork",
2437 "top",
2438 NULL
2441 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2442 return (NS_LDAP_OP_FAILED);
2443 *entry = e = __s_mk_entry(oclist, max_attr);
2444 if (e == NULL)
2445 return (NS_LDAP_MEMORY);
2447 /* Convert the structure */
2448 ptr = (struct netent *)data;
2450 if (ptr->n_name == NULL || ptr->n_net == 0) {
2451 __ns_ldap_freeEntry(e);
2452 *entry = NULL;
2453 return (NS_LDAP_INVALID_PARAM);
2456 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2457 (ptr->n_net & 0xFF000000) >> 24,
2458 (ptr->n_net & 0x00FF0000) >> 16,
2459 (ptr->n_net & 0x0000FF00) >> 8,
2460 (ptr->n_net & 0x000000FF));
2462 /* Create an appropriate rdn */
2463 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2464 *rdn = strdup(trdn);
2465 if (*rdn == NULL) {
2466 __ns_ldap_freeEntry(e);
2467 *entry = NULL;
2468 return (NS_LDAP_MEMORY);
2471 /* Error check the data and add the attributes */
2472 if (ptr->n_aliases && ptr->n_aliases[0]) {
2473 nm = ptr->n_aliases;
2474 for (i = 0; *nm; i++, nm++)
2476 nm = (char **)calloc(i+2, sizeof (char *));
2477 if (nm == NULL) {
2478 __s_cvt_freeEntryRdn(entry, rdn);
2479 return (NS_LDAP_MEMORY);
2481 nm[0] = ptr->n_name;
2482 for (j = 0; j < i; j++)
2483 nm[j+1] = ptr->n_aliases[j];
2485 rc = __s_add_attrlist(e, "cn", nm);
2486 free(nm);
2487 nm = NULL;
2488 if (rc != NS_LDAP_SUCCESS) {
2489 __s_cvt_freeEntryRdn(entry, rdn);
2490 return (rc);
2492 } else {
2493 rc = __s_add_attr(e, "cn", ptr->n_name);
2494 if (rc != NS_LDAP_SUCCESS) {
2495 __s_cvt_freeEntryRdn(entry, rdn);
2496 return (rc);
2500 rc = __s_add_attr(e, "ipNetworkNumber", cp);
2501 if (rc != NS_LDAP_SUCCESS) {
2502 __s_cvt_freeEntryRdn(entry, rdn);
2503 return (rc);
2506 return (NS_LDAP_SUCCESS);
2510 * Conversion: netmasks
2511 * Input format: struct _ns_netmasks
2512 * Exported objectclass: ipNetwork
2514 static int
2515 __s_cvt_netmasks(const void *data, char **rdn,
2516 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2518 ns_ldap_entry_t *e;
2519 int rc;
2520 char trdn[RDNSIZE];
2521 /* routine specific */
2522 struct _ns_netmasks *ptr;
2523 int max_attr = 4;
2524 static char *oclist[] = {
2525 "ipNetwork",
2526 "top",
2527 NULL
2530 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2531 return (NS_LDAP_OP_FAILED);
2532 *entry = e = __s_mk_entry(oclist, max_attr);
2533 if (e == NULL)
2534 return (NS_LDAP_MEMORY);
2536 /* Convert the structure */
2537 ptr = (struct _ns_netmasks *)data;
2539 if (ptr->netnumber == NULL) {
2540 __ns_ldap_freeEntry(e);
2541 *entry = NULL;
2542 return (NS_LDAP_INVALID_PARAM);
2545 /* Create an appropriate rdn */
2546 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2547 *rdn = strdup(trdn);
2548 if (*rdn == NULL) {
2549 __ns_ldap_freeEntry(e);
2550 *entry = NULL;
2551 return (NS_LDAP_MEMORY);
2554 /* Error check the data and add the attributes */
2555 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2556 if (rc != NS_LDAP_SUCCESS) {
2557 __s_cvt_freeEntryRdn(entry, rdn);
2558 return (rc);
2561 if (ptr->netmask != NULL) {
2562 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2563 if (rc != NS_LDAP_SUCCESS) {
2564 __s_cvt_freeEntryRdn(entry, rdn);
2565 return (rc);
2569 return (NS_LDAP_SUCCESS);
2573 * Conversion: netgroups
2574 * Input format: struct _ns_netgroups
2575 * Exported objectclass: nisNetgroup
2577 static int
2578 __s_cvt_netgroups(const void *data, char **rdn,
2579 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2581 ns_ldap_entry_t *e;
2582 int rc;
2583 char trdn[RDNSIZE];
2584 /* routine specific */
2585 struct _ns_netgroups *ptr;
2586 int max_attr = 6;
2587 int i, j;
2588 char **nm;
2589 static char *oclist[] = {
2590 "nisNetgroup",
2591 "top",
2592 NULL
2595 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2596 return (NS_LDAP_OP_FAILED);
2597 *entry = e = __s_mk_entry(oclist, max_attr);
2598 if (e == NULL)
2599 return (NS_LDAP_MEMORY);
2601 /* Convert the structure */
2602 ptr = (struct _ns_netgroups *)data;
2604 if (ptr->name == NULL || *ptr->name == '\0') {
2605 __ns_ldap_freeEntry(e);
2606 *entry = NULL;
2607 return (NS_LDAP_INVALID_PARAM);
2610 /* Create an appropriate rdn */
2611 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2612 *rdn = strdup(trdn);
2613 if (*rdn == NULL) {
2614 __ns_ldap_freeEntry(e);
2615 *entry = NULL;
2616 return (NS_LDAP_MEMORY);
2619 rc = __s_add_attr(e, "cn", ptr->name);
2620 if (rc != NS_LDAP_SUCCESS) {
2621 __s_cvt_freeEntryRdn(entry, rdn);
2622 return (rc);
2625 /* Error check the data and add the attributes */
2626 if (ptr->triplet && ptr->triplet[0]) {
2627 nm = ptr->triplet;
2628 for (i = 0; *nm; i++, nm++)
2630 nm = (char **)calloc(i+2, sizeof (char *));
2631 if (nm == NULL) {
2632 __s_cvt_freeEntryRdn(entry, rdn);
2633 return (NS_LDAP_MEMORY);
2635 for (j = 0; j < i; j++)
2636 nm[j] = ptr->triplet[j];
2638 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
2639 free(nm);
2640 nm = NULL;
2641 if (rc != NS_LDAP_SUCCESS) {
2642 __s_cvt_freeEntryRdn(entry, rdn);
2643 return (rc);
2646 if (ptr->netgroup && ptr->netgroup[0]) {
2647 nm = ptr->netgroup;
2648 for (i = 0; *nm; i++, nm++)
2650 nm = (char **)calloc(i+2, sizeof (char *));
2651 if (nm == NULL) {
2652 __s_cvt_freeEntryRdn(entry, rdn);
2653 return (NS_LDAP_MEMORY);
2655 for (j = 0; j < i; j++)
2656 nm[j] = ptr->netgroup[j];
2658 rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
2659 free(nm);
2660 nm = NULL;
2661 if (rc != NS_LDAP_SUCCESS) {
2662 __s_cvt_freeEntryRdn(entry, rdn);
2663 return (rc);
2666 return (NS_LDAP_SUCCESS);
2669 * Conversion: bootparams
2670 * Input format: struct _ns_bootp
2671 * Exported objectclass: bootableDevice, device
2673 static int
2674 __s_cvt_bootparams(const void *data, char **rdn,
2675 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2677 ns_ldap_entry_t *e;
2678 int rc;
2679 char trdn[RDNSIZE];
2680 /* routine specific */
2681 struct _ns_bootp *ptr;
2682 int max_attr = 4;
2683 int i, j;
2684 char **nm;
2685 static char *oclist[] = {
2686 "bootableDevice",
2687 "device",
2688 "top",
2689 NULL
2692 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2693 return (NS_LDAP_OP_FAILED);
2694 *entry = e = __s_mk_entry(oclist, max_attr);
2695 if (e == NULL)
2696 return (NS_LDAP_MEMORY);
2698 /* Convert the structure */
2699 ptr = (struct _ns_bootp *)data;
2701 if (ptr->name == NULL || *ptr->name == '\0') {
2702 __ns_ldap_freeEntry(e);
2703 *entry = NULL;
2704 return (NS_LDAP_INVALID_PARAM);
2707 /* Create an appropriate rdn */
2708 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2709 *rdn = strdup(trdn);
2710 if (*rdn == NULL) {
2711 __ns_ldap_freeEntry(e);
2712 *entry = NULL;
2713 return (NS_LDAP_MEMORY);
2716 rc = __s_add_attr(e, "cn", ptr->name);
2717 if (rc != NS_LDAP_SUCCESS) {
2718 __s_cvt_freeEntryRdn(entry, rdn);
2719 return (rc);
2722 /* Error check the data and add the attributes */
2723 if (ptr->param && ptr->param[0]) {
2724 nm = ptr->param;
2725 for (i = 0; *nm; i++, nm++)
2727 nm = (char **)calloc(i+2, sizeof (char *));
2728 if (nm == NULL) {
2729 __s_cvt_freeEntryRdn(entry, rdn);
2730 return (NS_LDAP_MEMORY);
2732 for (j = 0; j < i; j++)
2733 nm[j] = ptr->param[j];
2735 rc = __s_add_attrlist(e, "bootParameter", nm);
2736 free(nm);
2737 nm = NULL;
2738 if (rc != NS_LDAP_SUCCESS) {
2739 __s_cvt_freeEntryRdn(entry, rdn);
2740 return (rc);
2744 return (NS_LDAP_SUCCESS);
2748 * Conversion: ethers
2749 * Input format: struct _ns_ethers
2750 * Exported objectclass: ieee802Device, device
2752 static int
2753 __s_cvt_ethers(const void *data, char **rdn,
2754 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2756 ns_ldap_entry_t *e;
2757 int rc;
2758 char trdn[RDNSIZE];
2759 /* routine specific */
2760 struct _ns_ethers *ptr;
2761 int max_attr = 4;
2762 static char *oclist[] = {
2763 "ieee802Device",
2764 "device",
2765 "top",
2766 NULL
2769 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2770 return (NS_LDAP_OP_FAILED);
2771 *entry = e = __s_mk_entry(oclist, max_attr);
2772 if (e == NULL)
2773 return (NS_LDAP_MEMORY);
2775 /* Convert the structure */
2776 ptr = (struct _ns_ethers *)data;
2778 if (ptr->name == NULL || *ptr->name == '\0' || ptr->ether == NULL) {
2779 __ns_ldap_freeEntry(e);
2780 *entry = NULL;
2781 return (NS_LDAP_INVALID_PARAM);
2784 /* Create an appropriate rdn */
2785 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2786 *rdn = strdup(trdn);
2787 if (*rdn == NULL) {
2788 __ns_ldap_freeEntry(e);
2789 *entry = NULL;
2790 return (NS_LDAP_MEMORY);
2793 /* Error check the data and add the attributes */
2794 rc = __s_add_attr(e, "cn", ptr->name);
2795 if (rc != NS_LDAP_SUCCESS) {
2796 __s_cvt_freeEntryRdn(entry, rdn);
2797 return (rc);
2800 rc = __s_add_attr(e, "macAddress", ptr->ether);
2801 if (rc != NS_LDAP_SUCCESS) {
2802 __s_cvt_freeEntryRdn(entry, rdn);
2803 return (rc);
2806 return (NS_LDAP_SUCCESS);
2809 * This function is used when processing an ethers (objectclass: ieee802Device)
2810 * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2811 * already found in LDAP. Since both ethers and bootparams share the same
2812 * LDAP container, we want to check that the entry found in LDAP is:
2813 * - either the same entry (same cn, same objectclass): we don't do anything
2814 * in this case
2815 * - or an entry which does not have the objectclass we are interesting in:
2816 * in this case, we modify the existing entry by adding the relevant
2817 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2818 * from the attribute list previously computing by the relevant conversion
2819 * function.
2820 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams()
2821 * we know that there is only 1 more attribute today to add (macAddress
2822 * or bootParameter)
2824 #define _MAX_ATTR_ETHBOOTP 2
2825 static int
2826 modify_ethers_bootp(
2827 const char *service,
2828 const char *rdn,
2829 const char *fulldn,
2830 const ns_ldap_attr_t * const *attrlist,
2831 const ns_cred_t *cred,
2832 const int flags,
2833 ns_ldap_error_t **errorp)
2835 char filter[BUFSIZ];
2836 ns_ldap_result_t *resultp;
2837 int rc = 0;
2838 int i;
2839 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2840 ns_ldap_attr_t new_attrlist0;
2841 char *new_attrvalue0[1];
2842 const ns_ldap_attr_t * const *aptr = attrlist;
2843 ns_ldap_attr_t *aptr2;
2844 ns_ldap_error_t *new_errorp = NULL;
2846 if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2847 errorp == NULL || service == NULL)
2848 return (NS_LDAP_OP_FAILED);
2850 bzero(&new_attrlist, sizeof (new_attrlist));
2851 bzero(&new_attrlist0, sizeof (new_attrlist0));
2852 new_attrlist[0] = &new_attrlist0;
2853 new_attrlist[0]->attrvalue = new_attrvalue0;
2855 new_attrlist[0]->attrname = "objectclass";
2856 new_attrlist[0]->value_count = 1;
2857 if (strcasecmp(service, "ethers") == NULL) {
2858 (void) snprintf(&filter[0], sizeof (filter),
2859 "(&(objectClass=ieee802Device)(%s))", rdn);
2860 new_attrlist[0]->attrvalue[0] = "ieee802Device";
2861 } else {
2862 (void) snprintf(&filter[0], sizeof (filter),
2863 "(&(objectClass=bootableDevice)(%s))", rdn);
2864 new_attrlist[0]->attrvalue[0] = "bootableDevice";
2867 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2868 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2869 NULL, NULL);
2871 switch (rc) {
2872 case NS_LDAP_SUCCESS:
2874 * entry already exists for this service
2875 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2877 rc = NS_LDAP_INTERNAL;
2878 break;
2879 case NS_LDAP_NOTFOUND:
2881 * entry not found with the given objectclasss but entry exists
2882 * hence add the relevant attribute (macAddress or bootparams).
2884 i = 1;
2885 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2886 /* aptr2 needed here to avoid lint warning */
2887 aptr2 = (ns_ldap_attr_t *)*aptr++;
2888 if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2889 (strcasecmp(aptr2->attrname,
2890 "objectclass") != 0)) {
2891 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
2895 if (i != _MAX_ATTR_ETHBOOTP) {
2896 /* we haven't found all expected attributes */
2897 rc = NS_LDAP_OP_FAILED;
2898 break;
2901 aptr = (const ns_ldap_attr_t * const *) new_attrlist;
2902 /* clean errorp first */
2903 (void) __ns_ldap_freeError(errorp);
2904 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2905 errorp);
2906 break;
2907 default:
2909 * unexpected error happenned
2910 * returning relevant error
2912 (void) __ns_ldap_freeError(errorp);
2913 *errorp = new_errorp;
2914 break;
2917 return (rc);
2921 * Conversion: publickey
2922 * Input format: struct _ns_pubkey
2923 * Exported objectclass: NisKeyObject
2925 static int
2926 __s_cvt_publickey(const void *data, char **rdn,
2927 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2929 ns_ldap_entry_t *e;
2930 int rc;
2931 char trdn[RDNSIZE];
2932 /* routine specific */
2933 struct _ns_pubkey *ptr;
2934 int max_attr = 3;
2935 static char *oclist[] = {
2936 "NisKeyObject",
2937 NULL
2940 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2941 return (NS_LDAP_OP_FAILED);
2942 *entry = e = __s_mk_entry(oclist, max_attr);
2943 if (e == NULL)
2944 return (NS_LDAP_MEMORY);
2946 /* Convert the structure */
2947 ptr = (struct _ns_pubkey *)data;
2949 if (ptr->name == NULL || *ptr->name == '\0' || ptr->pubkey == NULL ||
2950 ptr->privkey == NULL) {
2951 __ns_ldap_freeEntry(e);
2952 *entry = NULL;
2953 return (NS_LDAP_INVALID_PARAM);
2956 /* Create an appropriate rdn */
2957 if (ptr->hostcred == NS_HOSTCRED_FALSE)
2958 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2959 else
2960 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2961 *rdn = strdup(trdn);
2962 if (*rdn == NULL) {
2963 __ns_ldap_freeEntry(e);
2964 *entry = NULL;
2965 return (NS_LDAP_MEMORY);
2968 /* Error check the data and add the attributes */
2970 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2971 if (rc != NS_LDAP_SUCCESS) {
2972 __s_cvt_freeEntryRdn(entry, rdn);
2973 return (rc);
2976 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2977 if (rc != NS_LDAP_SUCCESS) {
2978 __s_cvt_freeEntryRdn(entry, rdn);
2979 return (rc);
2982 return (NS_LDAP_SUCCESS);
2985 * Conversion: aliases
2986 * Input format: struct _ns_alias
2987 * Exported objectclass: mailGroup
2989 static int
2990 __s_cvt_aliases(const void *data, char **rdn,
2991 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2993 ns_ldap_entry_t *e;
2994 int rc;
2995 char trdn[RDNSIZE];
2996 /* routine specific */
2997 struct _ns_alias *ptr;
2998 int max_attr = 4;
2999 int i, j;
3000 char **nm;
3001 static char *oclist[] = {
3002 "mailGroup",
3003 "top",
3004 NULL
3007 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3008 return (NS_LDAP_OP_FAILED);
3009 *entry = e = __s_mk_entry(oclist, max_attr);
3010 if (e == NULL)
3011 return (NS_LDAP_MEMORY);
3013 /* Convert the structure */
3014 ptr = (struct _ns_alias *)data;
3016 if (ptr->alias == NULL || *ptr->alias == '\0') {
3017 __ns_ldap_freeEntry(e);
3018 *entry = NULL;
3019 return (NS_LDAP_INVALID_PARAM);
3022 /* Create an appropriate rdn */
3023 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
3024 *rdn = strdup(trdn);
3025 if (*rdn == NULL) {
3026 __ns_ldap_freeEntry(e);
3027 *entry = NULL;
3028 return (NS_LDAP_MEMORY);
3031 rc = __s_add_attr(e, "mail", (char *)ptr->alias);
3032 if (rc != NS_LDAP_SUCCESS) {
3033 __s_cvt_freeEntryRdn(entry, rdn);
3034 return (rc);
3037 /* Error check the data and add the attributes */
3038 if (ptr->member && ptr->member[0]) {
3039 nm = ptr->member;
3040 for (i = 0; *nm; i++, nm++)
3042 nm = (char **)calloc(i+2, sizeof (char *));
3043 if (nm == NULL) {
3044 __s_cvt_freeEntryRdn(entry, rdn);
3045 return (NS_LDAP_MEMORY);
3047 for (j = 0; j < i; j++)
3048 nm[j] = ptr->member[j];
3050 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
3051 free(nm);
3052 nm = NULL;
3053 if (rc != NS_LDAP_SUCCESS) {
3054 __s_cvt_freeEntryRdn(entry, rdn);
3055 return (rc);
3059 return (NS_LDAP_SUCCESS);
3063 * Conversion: automount
3064 * Input format: struct _ns_automount
3065 * Exported objectclass: automount
3067 static int
3068 __s_cvt_auto_mount(const void *data, char **rdn,
3069 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3071 ns_ldap_entry_t *e;
3072 int rc;
3073 char trdn[RDNSIZE];
3074 /* routine specific */
3075 struct _ns_automount *ptr;
3076 int max_attr = 6;
3077 void **paramVal = NULL;
3078 char **mappedschema = NULL;
3079 int version1 = 0;
3080 static char *oclist[] = {
3081 NULL,
3082 "top",
3083 NULL
3086 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3087 return (NS_LDAP_OP_FAILED);
3089 /* determine profile version number */
3090 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
3091 if (paramVal && *paramVal &&
3092 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
3093 version1 = 1;
3094 if (paramVal)
3095 (void) __ns_ldap_freeParam(&paramVal);
3096 if (rc && errorp)
3097 (void) __ns_ldap_freeError(errorp);
3099 /* use old schema for version 1 profiles */
3100 if (version1)
3101 oclist[0] = "nisObject";
3102 else
3103 oclist[0] = "automount";
3105 *entry = e = __s_mk_entry(oclist, max_attr);
3106 if (e == NULL)
3107 return (NS_LDAP_MEMORY);
3109 /* Convert the structure */
3110 ptr = (struct _ns_automount *)data;
3112 if (ptr->key == NULL || *ptr->key == '\0' || ptr->value == NULL ||
3113 ptr->mapname == NULL) {
3114 __ns_ldap_freeEntry(e);
3115 *entry = NULL;
3116 return (NS_LDAP_INVALID_PARAM);
3119 /* Create an appropriate rdn */
3120 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
3121 ptr->key);
3122 *rdn = strdup(trdn);
3123 if (*rdn == NULL) {
3124 __ns_ldap_freeEntry(e);
3125 *entry = NULL;
3126 return (NS_LDAP_MEMORY);
3129 rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
3130 (char *)ptr->key);
3131 if (rc != NS_LDAP_SUCCESS) {
3132 __s_cvt_freeEntryRdn(entry, rdn);
3133 return (rc);
3136 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
3137 (char *)ptr->value);
3138 if (rc != NS_LDAP_SUCCESS) {
3139 __s_cvt_freeEntryRdn(entry, rdn);
3140 return (rc);
3144 * even for version 2, if automount is mapped to nisObject we
3145 * still need 'nisMapName' attribute
3147 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
3148 if (mappedschema && mappedschema[0] &&
3149 strcasecmp(mappedschema[0], "nisObject") == 0)
3150 version1 = 1;
3151 if (mappedschema)
3152 __s_api_free2dArray(mappedschema);
3154 if (version1) {
3155 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
3156 if (rc != NS_LDAP_SUCCESS) {
3157 __s_cvt_freeEntryRdn(entry, rdn);
3158 return (rc);
3162 return (NS_LDAP_SUCCESS);
3165 * Conversion: auth_attr
3166 * Input format: authstr_t
3167 * Exported objectclass: SolarisAuthAttr
3169 static int
3170 __s_cvt_authattr(const void *data, char **rdn,
3171 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3173 ns_ldap_entry_t *e;
3174 int rc;
3175 char trdn[RDNSIZE];
3176 /* routine specific */
3177 authstr_t *ptr;
3178 int max_attr = 6;
3179 static char *oclist[] = {
3180 "SolarisAuthAttr",
3181 "top",
3182 NULL
3185 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3186 return (NS_LDAP_OP_FAILED);
3188 *entry = e = __s_mk_entry(oclist, max_attr);
3189 if (e == NULL)
3190 return (NS_LDAP_MEMORY);
3192 /* Convert the structure */
3193 ptr = (authstr_t *)data;
3195 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3196 __ns_ldap_freeEntry(e);
3197 *entry = NULL;
3198 return (NS_LDAP_INVALID_PARAM);
3201 /* Create an appropriate rdn */
3202 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3203 *rdn = strdup(trdn);
3204 if (*rdn == NULL) {
3205 __ns_ldap_freeEntry(e);
3206 *entry = NULL;
3207 return (NS_LDAP_MEMORY);
3210 rc = __s_add_attr(e, "cn", ptr->name);
3211 if (rc != NS_LDAP_SUCCESS) {
3212 __s_cvt_freeEntryRdn(entry, rdn);
3213 return (rc);
3216 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3217 if (rc != NS_LDAP_SUCCESS) {
3218 __s_cvt_freeEntryRdn(entry, rdn);
3219 return (rc);
3222 if (ptr->res1 != NULL) {
3223 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3224 if (rc != NS_LDAP_SUCCESS) {
3225 __s_cvt_freeEntryRdn(entry, rdn);
3226 return (rc);
3230 if (ptr->res2 != NULL) {
3231 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3232 if (rc != NS_LDAP_SUCCESS) {
3233 __s_cvt_freeEntryRdn(entry, rdn);
3234 return (rc);
3238 if (ptr->short_desc != NULL) {
3239 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
3240 if (rc != NS_LDAP_SUCCESS) {
3241 __s_cvt_freeEntryRdn(entry, rdn);
3242 return (rc);
3246 if (ptr->long_desc != NULL) {
3247 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
3248 if (rc != NS_LDAP_SUCCESS) {
3249 __s_cvt_freeEntryRdn(entry, rdn);
3250 return (rc);
3254 return (NS_LDAP_SUCCESS);
3257 * Conversion: exec_attr
3258 * Input format: execstr_t
3259 * Exported objectclass: SolarisExecAttr
3261 static int
3262 __s_cvt_execattr(const void *data, char **rdn,
3263 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3265 ns_ldap_entry_t *e;
3266 int rc;
3267 char trdn[RDNSIZE];
3268 char esc_str[RDNSIZE];
3269 /* routine specific */
3270 execstr_t *ptr;
3271 int max_attr = 7;
3272 static char *oclist[] = {
3273 "SolarisExecAttr",
3274 "SolarisProfAttr",
3275 "top",
3276 NULL
3279 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3280 return (NS_LDAP_OP_FAILED);
3282 *entry = e = __s_mk_entry(oclist, max_attr);
3283 if (e == NULL)
3284 return (NS_LDAP_MEMORY);
3286 /* Convert the structure */
3287 ptr = (execstr_t *)data;
3289 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3290 ptr->policy == NULL || ptr->policy[0] == '\0' ||
3291 ptr->type == NULL || ptr->type[0] == '\0' ||
3292 ptr->id == NULL || ptr->id[0] == '\0') {
3293 __ns_ldap_freeEntry(e);
3294 *entry = NULL;
3295 return (NS_LDAP_INVALID_PARAM);
3299 * Escape special characters in ProfileID.
3301 if (escape_str(esc_str, ptr->id) != 0) {
3302 __ns_ldap_freeEntry(e);
3303 *entry = NULL;
3304 return (NS_LDAP_INVALID_PARAM);
3307 /* Create an appropriate rdn */
3308 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
3309 "+SolarisProfileType=%s+SolarisProfileId=%s",
3310 ptr->name, ptr->policy, ptr->type, esc_str);
3312 *rdn = strdup(trdn);
3313 if (*rdn == NULL) {
3314 __ns_ldap_freeEntry(e);
3315 *entry = NULL;
3316 return (NS_LDAP_MEMORY);
3319 rc = __s_add_attr(e, "cn", ptr->name);
3320 if (rc != NS_LDAP_SUCCESS) {
3321 __s_cvt_freeEntryRdn(entry, rdn);
3322 return (rc);
3325 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
3326 if (rc != NS_LDAP_SUCCESS) {
3327 __s_cvt_freeEntryRdn(entry, rdn);
3328 return (rc);
3331 rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
3332 if (rc != NS_LDAP_SUCCESS) {
3333 __s_cvt_freeEntryRdn(entry, rdn);
3334 return (rc);
3337 rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
3338 if (rc != NS_LDAP_SUCCESS) {
3339 __s_cvt_freeEntryRdn(entry, rdn);
3340 return (rc);
3343 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3344 if (rc != NS_LDAP_SUCCESS) {
3345 __s_cvt_freeEntryRdn(entry, rdn);
3346 return (rc);
3349 if (ptr->res1 != NULL) {
3350 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
3351 if (rc != NS_LDAP_SUCCESS) {
3352 __s_cvt_freeEntryRdn(entry, rdn);
3353 return (rc);
3357 if (ptr->res2 != NULL) {
3358 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
3359 if (rc != NS_LDAP_SUCCESS) {
3360 __s_cvt_freeEntryRdn(entry, rdn);
3361 return (rc);
3365 return (NS_LDAP_SUCCESS);
3368 * Conversion: prof_attr
3369 * Input format: profstr_t
3370 * Exported objectclass: SolarisProfAttr
3372 static int
3373 __s_cvt_profattr(const void *data, char **rdn,
3374 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3376 ns_ldap_entry_t *e;
3377 int rc;
3378 char trdn[RDNSIZE];
3379 /* routine specific */
3380 profstr_t *ptr;
3381 int max_attr = 5;
3382 static char *oclist[] = {
3383 "SolarisProfAttr",
3384 "top",
3385 NULL
3388 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3389 return (NS_LDAP_OP_FAILED);
3391 *entry = e = __s_mk_entry(oclist, max_attr);
3392 if (e == NULL)
3393 return (NS_LDAP_MEMORY);
3395 /* Convert the structure */
3396 ptr = (profstr_t *)data;
3398 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3399 __ns_ldap_freeEntry(e);
3400 *entry = NULL;
3401 return (NS_LDAP_INVALID_PARAM);
3404 /* Create an appropriate rdn */
3405 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3406 *rdn = strdup(trdn);
3407 if (*rdn == NULL) {
3408 __ns_ldap_freeEntry(e);
3409 *entry = NULL;
3410 return (NS_LDAP_MEMORY);
3413 rc = __s_add_attr(e, "cn", ptr->name);
3414 if (rc != NS_LDAP_SUCCESS) {
3415 __s_cvt_freeEntryRdn(entry, rdn);
3416 return (rc);
3419 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3420 if (rc != NS_LDAP_SUCCESS) {
3421 __s_cvt_freeEntryRdn(entry, rdn);
3422 return (rc);
3425 if (ptr->res1 != NULL) {
3426 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3427 if (rc != NS_LDAP_SUCCESS) {
3428 __s_cvt_freeEntryRdn(entry, rdn);
3429 return (rc);
3433 if (ptr->res2 != NULL) {
3434 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3435 if (rc != NS_LDAP_SUCCESS) {
3436 __s_cvt_freeEntryRdn(entry, rdn);
3437 return (rc);
3441 if (ptr->desc != NULL) {
3442 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3443 if (rc != NS_LDAP_SUCCESS) {
3444 __s_cvt_freeEntryRdn(entry, rdn);
3445 return (rc);
3449 return (NS_LDAP_SUCCESS);
3452 * Conversion: user_attr
3453 * Input format: userstr_t
3454 * Exported objectclass: SolarisUserAttr
3456 static int
3457 __s_cvt_userattr(const void *data, char **rdn,
3458 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3460 ns_ldap_entry_t *e;
3461 int rc;
3462 char trdn[RDNSIZE];
3463 /* routine specific */
3464 userstr_t *ptr;
3465 int max_attr = 5;
3466 static char *oclist[] = {
3467 "SolarisUserAttr",
3468 NULL
3471 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3472 return (NS_LDAP_OP_FAILED);
3474 *entry = e = __s_mk_entry(oclist, max_attr);
3475 if (e == NULL)
3476 return (NS_LDAP_MEMORY);
3478 /* Convert the structure */
3479 ptr = (userstr_t *)data;
3481 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3482 ptr->attr == NULL) {
3483 __ns_ldap_freeEntry(e);
3484 *entry = NULL;
3485 return (NS_LDAP_INVALID_PARAM);
3488 /* Create an appropriate rdn */
3489 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3490 *rdn = strdup(trdn);
3491 if (*rdn == NULL) {
3492 __ns_ldap_freeEntry(e);
3493 *entry = NULL;
3494 return (NS_LDAP_MEMORY);
3498 * SolarisUserAttr has no uid attribute
3501 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3502 if (rc != NS_LDAP_SUCCESS) {
3503 __s_cvt_freeEntryRdn(entry, rdn);
3504 return (rc);
3507 if (ptr->qualifier != NULL) {
3508 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3509 if (rc != NS_LDAP_SUCCESS) {
3510 __s_cvt_freeEntryRdn(entry, rdn);
3511 return (rc);
3515 if (ptr->res1 != NULL) {
3516 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3517 if (rc != NS_LDAP_SUCCESS) {
3518 __s_cvt_freeEntryRdn(entry, rdn);
3519 return (rc);
3523 if (ptr->res2 != NULL) {
3524 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3525 if (rc != NS_LDAP_SUCCESS) {
3526 __s_cvt_freeEntryRdn(entry, rdn);
3527 return (rc);
3531 return (NS_LDAP_SUCCESS);
3534 * Conversion: audit_user
3535 * Input format: au_user_str_t
3536 * Exported objectclass: SolarisAuditUser
3538 static int
3539 __s_cvt_audituser(const void *data, char **rdn,
3540 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3542 ns_ldap_entry_t *e;
3543 int rc;
3544 char trdn[RDNSIZE];
3545 /* routine specific */
3546 au_user_str_t *ptr;
3547 int max_attr = 3;
3548 static char *oclist[] = {
3549 "SolarisAuditUser",
3550 NULL
3553 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3554 return (NS_LDAP_OP_FAILED);
3556 *entry = e = __s_mk_entry(oclist, max_attr);
3557 if (e == NULL)
3558 return (NS_LDAP_MEMORY);
3560 /* Convert the structure */
3561 ptr = (au_user_str_t *)data;
3563 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
3564 __ns_ldap_freeEntry(e);
3565 *entry = NULL;
3566 return (NS_LDAP_INVALID_PARAM);
3569 /* Create an appropriate rdn */
3570 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
3571 *rdn = strdup(trdn);
3572 if (*rdn == NULL) {
3573 __ns_ldap_freeEntry(e);
3574 *entry = NULL;
3575 return (NS_LDAP_MEMORY);
3579 * Solaris AuditUser has no uid attribute
3582 if (ptr->au_always != NULL) {
3583 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
3584 if (rc != NS_LDAP_SUCCESS) {
3585 __s_cvt_freeEntryRdn(entry, rdn);
3586 return (rc);
3590 if (ptr->au_never != NULL) {
3591 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
3592 if (rc != NS_LDAP_SUCCESS) {
3593 __s_cvt_freeEntryRdn(entry, rdn);
3594 return (rc);
3598 return (NS_LDAP_SUCCESS);
3601 * Conversion: tnrhtp
3602 * Input format: tsol_tpstr_t
3603 * Exported objectclass: ipTnetTemplate
3605 static int
3606 __s_cvt_tnrhtp(const void *data, char **rdn,
3607 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3609 ns_ldap_entry_t *e;
3610 int rc;
3611 char trdn[RDNSIZE];
3612 char esc_str[RDNSIZE];
3613 /* routine specific */
3614 int max_attr = 2;
3615 tsol_tpstr_t *ptr;
3616 static char *oclist[] = {
3617 "ipTnetTemplate",
3618 "top",
3619 NULL
3622 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3623 return (NS_LDAP_OP_FAILED);
3625 *entry = e = __s_mk_entry(oclist, max_attr);
3626 if (e == NULL)
3627 return (NS_LDAP_MEMORY);
3629 /* Convert the structure */
3630 ptr = (tsol_tpstr_t *)data;
3632 if (ptr->template == NULL || *ptr->template == '\0') {
3633 __ns_ldap_freeEntry(e);
3634 *entry = NULL;
3635 return (NS_LDAP_INVALID_PARAM);
3639 * Escape special characters in Template name.
3641 if (escape_str(esc_str, ptr->template) != 0) {
3642 __ns_ldap_freeEntry(e);
3643 *entry = NULL;
3644 return (NS_LDAP_INVALID_PARAM);
3647 /* Create an appropriate rdn */
3648 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str);
3649 *rdn = strdup(trdn);
3650 if (*rdn == NULL) {
3651 __ns_ldap_freeEntry(e);
3652 *entry = NULL;
3653 return (NS_LDAP_MEMORY);
3656 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3657 if (rc != NS_LDAP_SUCCESS) {
3658 __s_cvt_freeEntryRdn(entry, rdn);
3659 return (rc);
3662 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs);
3663 if (rc != NS_LDAP_SUCCESS) {
3664 __s_cvt_freeEntryRdn(entry, rdn);
3665 return (rc);
3668 return (NS_LDAP_SUCCESS);
3671 * Conversion: tnrhdb
3672 * Input format: tsol_rhstr_t
3673 * Exported objectclass: ipTnetHost
3675 static int
3676 __s_cvt_tnrhdb(const void *data, char **rdn,
3677 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3679 ns_ldap_entry_t *e;
3680 int rc;
3681 char trdn[RDNSIZE];
3682 /* routine specific */
3683 tsol_rhstr_t *ptr;
3684 int max_attr = 2;
3685 static char *oclist[] = {
3686 "ipTnetHost",
3687 "ipTnetTemplate",
3688 "top",
3689 NULL
3692 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3693 return (NS_LDAP_OP_FAILED);
3695 *entry = e = __s_mk_entry(oclist, max_attr);
3696 if (e == NULL)
3697 return (NS_LDAP_MEMORY);
3699 /* Convert the structure */
3700 ptr = (tsol_rhstr_t *)data;
3702 if (ptr->address == NULL || *ptr->address == '\0' ||
3703 ptr->template == NULL || *ptr->template == '\0') {
3704 __ns_ldap_freeEntry(e);
3705 *entry = NULL;
3706 return (NS_LDAP_INVALID_PARAM);
3709 /* Create an appropriate rdn */
3710 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address);
3711 *rdn = strdup(trdn);
3712 if (*rdn == NULL) {
3713 __ns_ldap_freeEntry(e);
3714 *entry = NULL;
3715 return (NS_LDAP_MEMORY);
3718 rc = __s_add_attr(e, "ipTnetNumber", ptr->address);
3719 if (rc != NS_LDAP_SUCCESS) {
3720 __s_cvt_freeEntryRdn(entry, rdn);
3721 return (rc);
3724 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3725 if (rc != NS_LDAP_SUCCESS) {
3726 __s_cvt_freeEntryRdn(entry, rdn);
3727 return (rc);
3730 return (NS_LDAP_SUCCESS);
3733 * Add Typed Entry Conversion data structures
3736 typedef struct __ns_cvt_type {
3737 const char *service;
3738 int flags;
3739 #define AE 1 /* alway add entries */
3740 int (*cvt_rtn)(const void *data,
3741 char **rdn,
3742 ns_ldap_entry_t **entry,
3743 ns_ldap_error_t **errorp);
3744 } __ns_cvt_type_t;
3746 static __ns_cvt_type_t __s_cvtlist[] = {
3747 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd },
3748 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group },
3749 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts },
3750 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts },
3751 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc },
3752 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols },
3753 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks },
3754 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups },
3755 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases },
3756 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services },
3757 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers },
3758 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow },
3759 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks },
3760 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams },
3761 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr },
3762 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr },
3763 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr },
3764 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr },
3765 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
3766 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
3767 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser },
3768 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp },
3769 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb },
3770 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project },
3771 { NULL, 0, NULL },
3775 * Add Typed Entry Routine
3778 /*ARGSUSED*/
3779 int __ns_ldap_addTypedEntry(
3780 const char *servicetype,
3781 const char *basedn,
3782 const void *data,
3783 const int create,
3784 const ns_cred_t *cred,
3785 const int flags,
3786 ns_ldap_error_t **errorp)
3788 char *rdn = NULL, *fulldn = NULL;
3789 void **paramVal = NULL;
3790 ns_ldap_entry_t *entry = NULL;
3791 const ns_ldap_attr_t *const *modattrlist;
3792 ns_ldap_search_desc_t **sdlist;
3793 char **dns = NULL;
3794 char trdn[RDNSIZE];
3795 char service[BUFSIZE];
3796 int rc = 0;
3797 int automount = 0;
3798 int i, s;
3800 rc = NS_LDAP_OP_FAILED;
3801 for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3802 if (__s_cvtlist[s].cvt_rtn == NULL)
3803 continue;
3804 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3805 break;
3806 /* Or, check if the servicetype is auto_ */
3807 if (strcmp(__s_cvtlist[s].service,
3808 NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3809 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3810 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3811 automount++;
3812 break;
3815 if (__s_cvtlist[s].service == NULL)
3816 return (rc);
3818 /* Convert the data */
3819 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3820 if (rc != NS_LDAP_SUCCESS) {
3821 __s_cvt_freeEntryRdn(&entry, &rdn);
3822 return (rc);
3824 if (rdn == NULL) {
3825 __ns_ldap_freeEntry(entry);
3826 return (NS_LDAP_OP_FAILED);
3829 if (strcmp(servicetype, "publickey") == 0) {
3830 struct _ns_pubkey *ptr;
3831 ptr = (struct _ns_pubkey *)data;
3832 if (ptr->hostcred == NS_HOSTCRED_TRUE)
3833 (void) strcpy(service, "hosts");
3834 else
3835 (void) strcpy(service, "passwd");
3836 } else
3837 (void) strcpy(service, servicetype);
3839 /* Create the Full DN */
3840 if (basedn == NULL) {
3841 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3842 &sdlist, errorp);
3843 if (rc != NS_LDAP_SUCCESS) {
3844 __s_cvt_freeEntryRdn(&entry, &rdn);
3845 return (rc);
3848 if (sdlist == NULL) {
3849 rc = __s_api_getDNs(&dns, service, errorp);
3850 if (rc != NS_LDAP_SUCCESS) {
3851 if (dns) {
3852 __s_api_free2dArray(dns);
3853 dns = NULL;
3855 __s_cvt_freeEntryRdn(&entry, &rdn);
3856 return (rc);
3858 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3859 __s_api_free2dArray(dns);
3860 } else {
3861 if (sdlist[0]->basedn) {
3862 (void) snprintf(trdn, RDNSIZE, "%s,%s",
3863 rdn, sdlist[0]->basedn);
3864 } else {
3865 __s_cvt_freeEntryRdn(&entry, &rdn);
3866 return (NS_LDAP_OP_FAILED);
3869 i = strlen(trdn) - 1;
3870 if (trdn[i] == COMMATOK) {
3871 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3872 &paramVal, errorp);
3873 if (rc != NS_LDAP_SUCCESS) {
3874 __s_cvt_freeEntryRdn(&entry, &rdn);
3875 return (rc);
3877 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3878 fulldn = (char *)calloc(i, 1);
3879 if (fulldn == NULL) {
3880 (void) __ns_ldap_freeParam(&paramVal);
3881 __s_cvt_freeEntryRdn(&entry, &rdn);
3882 return (NS_LDAP_MEMORY);
3884 (void) snprintf(fulldn, i, "%s%s", trdn,
3885 (char *)(paramVal[0]));
3886 (void) __ns_ldap_freeParam(&paramVal);
3887 } else {
3888 fulldn = strdup(trdn);
3889 if (fulldn == NULL) {
3890 __s_cvt_freeEntryRdn(&entry, &rdn);
3891 return (NS_LDAP_MEMORY);
3894 } else {
3895 i = strlen(rdn) + strlen(basedn) + 2;
3896 fulldn = (char *)calloc(i, 1);
3897 if (fulldn == NULL) {
3898 __s_cvt_freeEntryRdn(&entry, &rdn);
3899 return (NS_LDAP_MEMORY);
3901 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3904 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3905 /* Check to see if the entry exists already */
3906 /* May need to delete or update first */
3908 if (create != 1) {
3909 /* Modify the entry */
3911 * To add a shadow-like entry, the addTypedEntry function
3912 * would call __ns_ldap_repAttr first, and if server says
3913 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
3914 * This is to allow a netmask entry to be added even if the
3915 * base network entry is not in the directory. It would work
3916 * because the difference between the schema for the network
3917 * and netmask data contains only MAY attributes.
3919 * But for shadow data, the attributes do not have MUST
3920 * attributes the base entry needs, so if the __ns_ldap_addEntry
3921 * is executed, it would fail. The real reason, however, is that
3922 * the base entry did not exist. So returning
3923 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
3925 if ((__s_cvtlist[s].flags & AE) != 0)
3926 rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3927 cred, flags, errorp);
3928 else {
3929 rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3930 cred, flags, errorp);
3931 if (rc == NS_LDAP_INTERNAL && *errorp &&
3932 (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3933 (void) __ns_ldap_freeError(errorp);
3934 rc = __ns_ldap_addEntry(service, fulldn,
3935 entry, cred, flags, errorp);
3936 if (rc == NS_LDAP_INTERNAL && *errorp &&
3937 (*errorp)->status ==
3938 LDAP_OBJECT_CLASS_VIOLATION)
3939 (*errorp)->status = LDAP_NO_SUCH_OBJECT;
3942 } else {
3943 /* Add the entry */
3944 rc = __ns_ldap_addEntry(service, fulldn, entry,
3945 cred, flags, errorp);
3946 if (rc == NS_LDAP_INTERNAL && *errorp &&
3947 (*errorp)->status == LDAP_ALREADY_EXISTS &&
3948 ((strcmp(service, "ethers") == 0) ||
3949 (strcmp(service, "bootparams") == 0))) {
3950 rc = modify_ethers_bootp(service, rdn, fulldn,
3951 modattrlist, cred, flags, errorp);
3955 /* Free up entry created by conversion routine */
3956 if (fulldn != NULL)
3957 free(fulldn);
3958 __s_cvt_freeEntryRdn(&entry, &rdn);
3959 return (rc);
3964 * Append the default base dn to the dn
3965 * when it ends with ','.
3966 * e.g.
3967 * SSD = service:ou=foo,
3970 __s_api_append_default_basedn(const char *dn, char **new_dn, int *allocated,
3971 ns_ldap_error_t **errp)
3974 int rc = NS_LDAP_SUCCESS, len = 0;
3975 void **param = NULL;
3976 char *str = NULL;
3978 *allocated = FALSE;
3979 *new_dn = NULL;
3981 if (dn == NULL)
3982 return (NS_LDAP_INVALID_PARAM);
3984 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3985 (void ***)&param, errp);
3987 if (rc != NS_LDAP_SUCCESS) {
3988 if (param)
3989 (void) __ns_ldap_freeParam(&param);
3990 return (rc);
3993 len = strlen(dn);
3994 str = ((char **)param)[0];
3995 len = len + strlen(str) +1;
3996 *new_dn = (char *)malloc(len);
3997 if (*new_dn == NULL) {
3998 (void) __ns_ldap_freeParam(&param);
3999 return (NS_LDAP_MEMORY);
4001 *allocated = TRUE;
4003 (void) strcpy(*new_dn, dn);
4004 (void) strcat(*new_dn, str);
4006 (void) __ns_ldap_freeParam(&param);
4007 return (NS_LDAP_SUCCESS);
4011 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
4012 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
4013 * The output contains a count, a list of offsets, which show where the
4014 * corresponding copied attribute type and attribute value are located.
4015 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
4016 * the output is the ldap_strlist_t structure with: ldap_count = 6,
4017 * (buf + ldap_offsets[0]) -> "dn"
4018 * (buf + ldap_offsets[1]) -> "aaaa"
4019 * (buf + ldap_offsets[2]) -> "userPassword"
4020 * (buf + ldap_offsets[3]) -> "bbbb"
4021 * (buf + ldap_offsets[4]) -> "shadowlastchange"
4022 * (buf + ldap_offsets[5]) -> "cccc"
4023 * and all the string data shown above copied into the buffer after
4024 * the offset array. The total length of the data will be the return
4025 * value, or -1 if error.
4027 static int
4028 attr2list(const char *dn, ns_ldap_attr_t **attr,
4029 char *buf, int bufsize)
4031 int c = 0;
4032 char *ap;
4033 int ao;
4034 ldap_strlist_t *al = (ldap_strlist_t *)buf;
4035 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
4036 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
4038 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
4039 if ((strlen(dn) + 2 + 1) >= bufsize)
4040 return (-1);
4042 /* count number of attributes */
4043 while (*aptr++)
4044 c++;
4045 al->ldap_count = 2 + c * 2;
4046 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
4047 al->ldap_count;
4048 if (ao > bufsize)
4049 return (-1);
4050 al->ldap_offsets[0] = ao;
4051 ap = buf + ao;
4052 ao += 3;
4054 /* copy entry DN */
4055 if (ao > bufsize)
4056 return (-1);
4057 (void) strlcpy(ap, "dn", bufsize);
4058 ap += 3;
4060 al->ldap_offsets[1] = ao;
4061 ao += strlen(dn) + 1;
4062 if (ao > bufsize)
4063 return (-1);
4064 (void) strlcpy(ap, dn, bufsize);
4065 ap = buf + ao;
4067 aptr = attr;
4068 for (c = 2; c < al->ldap_count; c++, aptr++) {
4069 a = *aptr;
4070 if (a->attrname == NULL || a->attrvalue == NULL ||
4071 a->value_count != 1 || a->attrvalue[0] == NULL)
4072 return (-1);
4073 al->ldap_offsets[c] = ao;
4074 ao += strlen(a->attrname) + 1;
4075 if (ao > bufsize)
4076 return (-1);
4077 (void) strlcpy(ap, a->attrname, bufsize);
4078 ap = buf + ao;
4080 c++;
4081 al->ldap_offsets[c] = ao;
4082 ao += strlen(a->attrvalue[0]) + 1;
4083 (void) strlcpy(ap, a->attrvalue[0], bufsize);
4084 ap = buf + ao;
4087 return (ao);
4091 * Send a modify request to the ldap_cachemgr daemon
4092 * which will use the admin credential to perform the
4093 * operation.
4096 static int
4097 send_to_cachemgr(
4098 const char *dn,
4099 ns_ldap_attr_t **attr,
4100 ns_ldap_error_t **errorp)
4102 union {
4103 ldap_data_t s_d;
4104 char s_b[DOORBUFFERSIZE];
4105 } space;
4107 ldap_data_t *sptr;
4108 int ndata;
4109 int adata;
4110 int len;
4111 int rc;
4112 char errstr[MAXERROR];
4113 ldap_admin_mod_result_t *admin_result;
4115 *errorp = NULL;
4116 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
4117 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
4118 sizeof (space) - offsetof(ldap_return_t, ldap_u));
4119 if (len <= 0)
4120 return (NS_LDAP_INVALID_PARAM);
4122 adata = sizeof (ldap_call_t) + len;
4123 ndata = sizeof (space);
4124 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
4125 sptr = &space.s_d;
4127 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
4128 case NS_CACHE_SUCCESS:
4129 break;
4130 case NS_CACHE_NOTFOUND:
4131 (void) snprintf(errstr, sizeof (errstr),
4132 gettext("Door call ADMINMODIFY to "
4133 "ldap_cachemgr failed - error: %d"),
4134 space.s_d.ldap_ret.ldap_errno);
4135 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
4136 strdup(errstr), NULL);
4137 return (NS_LDAP_OP_FAILED);
4138 default:
4139 return (NS_LDAP_OP_FAILED);
4142 admin_result = &sptr->ldap_ret.ldap_u.admin_result;
4143 if (admin_result->ns_err == NS_LDAP_SUCCESS)
4144 rc = NS_LDAP_SUCCESS;
4145 else {
4146 rc = admin_result->ns_err;
4147 if (admin_result->msg_size == 0)
4148 *errorp = __s_api_make_error(admin_result->status,
4149 NULL);
4150 else
4151 *errorp = __s_api_make_error(admin_result->status,
4152 admin_result->msg);
4155 /* clean up the door call */
4156 if (sptr != &space.s_d) {
4157 (void) munmap((char *)sptr, ndata);
4160 return (rc);