dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libsldap / common / ns_writes.c
blob4e0b0b8f92fee7a973603725d2b3a081db4f074d
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>
63 static int send_to_cachemgr(const char *,
64 ns_ldap_attr_t **, ns_ldap_error_t **);
66 static int escape_str(char *, char *);
69 * If the rdn is a mapped attr:
70 * return NS_LDAP_SUCCESS and a new_dn.
71 * If no mapped attr is found in the rdn:
72 * return NS_LDAP_SUCCESS and *new_dn == NULL
73 * For example:
74 * service = abc
75 * dn = cn=foo,dc=bar,dc=com
76 * attributeMapping: abc:cn=sn
77 * Then:
78 * new_dn = sn=foo,dc=bar,dc=com
81 static int
82 replace_mapped_attr_in_dn(
83 const char *service, const char *dn, char **new_dn)
85 char **mappedattr;
86 char **dnArray = NULL;
87 char *rservice;
88 char *cur = NULL;
89 int len = 0, orig_len = 0, mapped_len = 0;
90 int dn_len = 0;
92 *new_dn = NULL;
95 * separate dn into individual componets
96 * e.g.
97 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
99 dnArray = ldap_explode_dn(dn, 0);
100 if (!dnArray || !*dnArray)
101 return (NS_LDAP_INVALID_PARAM);
103 cur = strchr(dnArray[0], '=');
104 if (!cur) {
105 __s_api_free2dArray(dnArray);
106 return (NS_LDAP_INVALID_PARAM);
108 *cur = '\0';
110 /* we only check schema mapping for automount, not for auto_* */
111 if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
112 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
113 rservice = "automount";
114 else
115 rservice = (char *)service;
117 mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]);
118 if (!mappedattr || !mappedattr[0]) {
119 __s_api_free2dArray(dnArray);
120 if (mappedattr)
121 __s_api_free2dArray(mappedattr);
122 return (NS_LDAP_SUCCESS);
124 orig_len = strlen(dnArray[0]);
127 * The new length is *dn length + (difference between
128 * orig attr and mapped attr) + 1 ;
129 * e.g.
130 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
131 * ==>
132 * cn=aa,automountMapName=auto_home,dc=foo,dc=com
134 mapped_len = strlen(mappedattr[0]);
135 dn_len = strlen(dn);
136 len = dn_len - orig_len + mapped_len + 1;
137 *new_dn = (char *)calloc(1, len);
138 if (*new_dn == NULL) {
139 __s_api_free2dArray(dnArray);
140 __s_api_free2dArray(mappedattr);
141 return (NS_LDAP_MEMORY);
144 (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
145 __s_api_free2dArray(dnArray);
146 __s_api_free2dArray(mappedattr);
148 return (NS_LDAP_SUCCESS);
153 * The following function is only used by the
154 * "gecos" 1 to N attribute mapping code. It expects
155 * and handle only one data/length pair.
157 static int
158 init_bval_mod(
159 LDAPMod *mod,
160 int mop,
161 char *mtype,
162 char *mvptr,
163 int mvlen)
166 struct berval **bmodval;
168 /* dup attribute name */
169 mod->mod_type = strdup(mtype);
170 if (mod->mod_type == NULL)
171 return (-1);
174 * assume single value,
175 * since only one value/length pair passed in
177 bmodval = (struct berval **)calloc(2, sizeof (struct berval *));
178 if (bmodval == NULL) {
179 free(mod->mod_type);
180 mod->mod_type = NULL;
181 return (-1);
183 bmodval[0] = (struct berval *)calloc(1, sizeof (struct berval));
184 if (bmodval[0] == NULL) {
185 free(mod->mod_type);
186 mod->mod_type = NULL;
187 free(bmodval);
188 return (-1);
191 /* set pointer to data */
192 bmodval[0]->bv_val = mvptr;
194 /* set length */
195 bmodval[0]->bv_len = mvlen;
198 * turn on the BVALUE bit to indicate
199 * that the length of data is supplied
201 mod->mod_op = mop | LDAP_MOD_BVALUES;
203 mod->mod_bvalues = bmodval;
205 return (0);
208 static void
209 freeModList(LDAPMod **mods)
211 int i, j;
212 int name_is_oc;
214 if (mods == NULL)
215 return;
217 for (i = 0; mods[i]; i++) {
219 /* free attribute name */
220 name_is_oc = FALSE;
221 if (mods[i]->mod_type) {
222 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0)
223 name_is_oc = TRUE;
224 free(mods[i]->mod_type);
227 if (mods[i]->mod_bvalues == NULL)
228 continue;
230 * LDAP_MOD_BVALUES is only set by
231 * the "gecos" 1 to N attribute mapping
232 * code, and the attribute is single valued.
234 if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
235 free(mods[i]->mod_bvalues[0]);
236 } else {
237 if (name_is_oc) {
239 * only values for the "objectclass"
240 * were dupped using strdup.
241 * other attribute values were
242 * not dupped, but via pointer
243 * assignment. So here the
244 * values for "objectclass"
245 * is freed one by one,
246 * but the values for other
247 * attributes need not be freed.
249 for (j = 0; mods[i]->mod_values[j]; j++)
250 free(mods[i]->mod_values[j]);
254 free(mods[i]->mod_bvalues);
257 /* modlist */
258 free((char *)(mods[0]));
259 free(mods);
262 static LDAPMod **
263 __s_api_makeModListCount(
264 const char *service,
265 const ns_ldap_attr_t * const *attr,
266 const int mod_op,
267 const int count,
268 const int flags)
270 LDAPMod **mods, *modlist;
271 char **modval;
272 char **mapping;
273 int i;
274 int j;
275 int k, rc, vlen;
276 char *c, *comma1 = NULL, *comma2 = NULL;
277 int schema_mapping_existed = FALSE;
278 int auto_service = FALSE;
282 * add 2 for "gecos" 1 to up to 3 attribute mapping
284 mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
285 if (mods == NULL) {
286 return (NULL);
289 * add 2 for "gecos" 1 to up to 3 attribute mapping
291 modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
292 if (modlist == NULL) {
293 free(mods);
294 return (NULL);
297 if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
298 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
299 auto_service = TRUE;
302 * see if schema mapping existed for the given service
304 mapping = __ns_ldap_getOrigAttribute(service,
305 NS_HASH_SCHEMA_MAPPING_EXISTED);
306 if (mapping) {
307 schema_mapping_existed = TRUE;
308 __s_api_free2dArray(mapping);
309 mapping = NULL;
312 for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
313 mods[i] = &modlist[i];
314 mods[i]->mod_op = mod_op;
316 * Perform attribute mapping if necessary.
318 if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) {
319 mapping = __ns_ldap_getMappedAttributes(service,
320 attr[k]->attrname);
321 } else
322 mapping = NULL;
324 if (mapping == NULL && auto_service &&
325 (flags & NS_LDAP_NOMAP) == 0) {
327 * if service == auto_xxx and
328 * no mapped attribute is found
329 * and NS_LDAP_NOMAP is not set
330 * then try automount's mapped attribute
332 mapping = __ns_ldap_getMappedAttributes("automount",
333 attr[k]->attrname);
336 if (mapping == NULL) {
337 mods[i]->mod_type = strdup(attr[k]->attrname);
338 if (mods[i]->mod_type == NULL)
339 goto free_memory;
340 } else {
342 * 1 to N attribute mapping is only done for "gecos",
343 * and only 1 to 3 mapping.
344 * nine cases here:
346 * A. attrMap=passwd:gecos=a
347 * 1. gecos="xx,yy,zz" -> a="xx,yy,zz"
348 * 2. gecos="xx,yy" -> a="xx,yy"
349 * 3. gecos="xx" -> a="xx"
351 * B. attrMap=passwd:gecos=a b
352 * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
353 * 5. gecos="xx,yy" -> a="xx" b="yy"
354 * 6. gecos="xx" -> a="xx"
356 * C. attrMap=passwd:gecos=a b c
357 * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
358 * 8. gecos="xx,yy" -> a="xx" b="yy"
359 * 9. gecos="xx" -> a="xx"
361 * This can be grouped as:
363 * c1 cases: 1,2,3,6,9
364 * if ((attrMap=passwd:gecos=a) ||
365 * (no "," in gecos value))
366 * same as other no-mapping attributes,
367 * no special processing needed
368 * else
370 * c2 cases: 4,5,8
371 * if ((attrMap=passwd:gecos=a b) ||
372 * (only one "," in gecos value))
373 * a=xx b=yy[,...]
374 * else
376 * c3 case: 7
377 * a=xx b=yy c=...
379 * notes: in case c2 and c3, ... could still contain ","
381 if (strcasecmp(service, "passwd") == 0 &&
382 strcasecmp(attr[k]->attrname, "gecos") == 0 &&
383 mapping[1] && attr[k]->attrvalue[0] &&
384 (comma1 = strchr(attr[k]->attrvalue[0],
385 COMMATOK)) != NULL) {
387 /* is there a second comma? */
388 if (*(comma1 + 1) != '\0')
389 comma2 = strchr(comma1 + 1, COMMATOK);
392 * Process case c2 or c3.
393 * case c2: mapped to two attributes or just
394 * one comma
396 if (mapping[2] == NULL || comma2 == NULL) {
397 /* case c2 */
400 * int mod structure for the first attribute
402 vlen = comma1 - attr[k]->attrvalue[0];
403 c = attr[k]->attrvalue[0];
405 if (vlen > 0 && c) {
406 rc = init_bval_mod(mods[i], mod_op,
407 mapping[0], c, vlen);
408 if (rc != 0)
409 goto free_memory;
410 } else {
411 /* don't leave a hole in mods array */
412 mods[i] = NULL;
413 i--;
418 * init mod structure for the 2nd attribute
420 if (*(comma1 + 1) == '\0') {
421 __s_api_free2dArray(mapping);
422 mapping = NULL;
423 continue;
426 i++;
427 mods[i] = &modlist[i];
430 * get pointer to data.
431 * Skip leading spaces.
433 for (c = comma1 + 1; *c == SPACETOK; c++) {
434 /* empty */
437 /* get data length */
438 vlen = strlen(attr[k]->attrvalue[0]) -
439 (c - attr[k]->attrvalue[0]);
441 if (vlen > 0 && c) {
442 rc = init_bval_mod(mods[i], mod_op,
443 mapping[1], c, vlen);
444 if (rc != 0)
445 goto free_memory;
446 } else {
447 /* don't leave a hole in mods array */
448 mods[i] = NULL;
449 i--;
452 /* done with the mapping array */
453 __s_api_free2dArray(mapping);
454 mapping = NULL;
456 continue;
457 } else {
458 /* case c3 */
461 * int mod structure for the first attribute
463 vlen = comma1 - attr[k]->attrvalue[0];
464 c = attr[k]->attrvalue[0];
466 if (vlen > 0 && c) {
467 rc = init_bval_mod(mods[i], mod_op,
468 mapping[0], c, vlen);
469 if (rc != 0)
470 goto free_memory;
471 } else {
472 /* don't leave a hole in mods array */
473 mods[i] = NULL;
474 i--;
478 * init mod structure for the 2nd attribute
480 i++;
481 mods[i] = &modlist[i];
484 * get pointer to data.
485 * Skip leading spaces.
487 for (c = comma1 + 1; *c == SPACETOK; c++) {
488 /* empty */
491 /* get data length */
492 vlen = comma2 - c;
494 if (vlen > 0 && c) {
495 rc = init_bval_mod(mods[i], mod_op,
496 mapping[1], c, vlen);
497 if (rc != 0)
498 goto free_memory;
499 } else {
500 /* don't leave a hole in mods array */
501 mods[i] = NULL;
502 i--;
506 * init mod structure for the 3rd attribute
508 if (*(comma2 + 1) == '\0') {
509 __s_api_free2dArray(mapping);
510 mapping = NULL;
511 continue;
514 i++;
515 mods[i] = &modlist[i];
517 * get pointer to data.
518 * Skip leading spaces.
520 for (c = comma2 + 1; *c == SPACETOK; c++) {
521 /* empty */
524 /* get data length */
525 vlen = strlen(attr[k]->attrvalue[0]) -
526 (c - attr[k]->attrvalue[0]);
528 if (vlen > 0 && c) {
529 rc = init_bval_mod(mods[i], mod_op,
530 mapping[2], c, vlen);
531 if (rc != 0)
532 goto free_memory;
533 } else {
534 /* don't leave a hole in mods array */
535 mods[i] = NULL;
536 i--;
539 /* done with the mapping array */
540 __s_api_free2dArray(mapping);
541 mapping = NULL;
543 continue;
547 /* case c1 */
548 mods[i]->mod_type = strdup(mapping[0]);
549 if (mods[i]->mod_type == NULL) {
550 goto free_memory;
552 __s_api_free2dArray(mapping);
553 mapping = NULL;
556 modval = (char **)calloc(attr[k]->value_count+1,
557 sizeof (char *));
558 if (modval == NULL)
559 goto free_memory;
561 * Perform objectclass mapping.
562 * Note that the values for the "objectclass" attribute
563 * will be dupped using strdup. Values for other
564 * attributes will be referenced via pointer
565 * assignments.
567 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
568 for (j = 0; j < attr[k]->value_count; j++) {
569 if (schema_mapping_existed &&
570 (flags & NS_LDAP_NOMAP) == 0)
571 mapping =
572 __ns_ldap_getMappedObjectClass(
573 service, attr[k]->attrvalue[j]);
574 else
575 mapping = NULL;
577 if (mapping == NULL && auto_service &&
578 (flags & NS_LDAP_NOMAP) == 0)
580 * if service == auto_xxx and
581 * no mapped objectclass is found
582 * then try automount
584 mapping =
585 __ns_ldap_getMappedObjectClass(
586 "automount", attr[k]->attrvalue[j]);
588 if (mapping && mapping[0]) {
589 /* assume single mapping */
590 modval[j] = strdup(mapping[0]);
591 } else {
592 modval[j] = strdup(attr[k]->
593 attrvalue[j]);
595 if (modval[j] == NULL)
596 goto free_memory;
598 } else {
599 for (j = 0; j < attr[k]->value_count; j++) {
600 /* ASSIGN NOT COPY */
601 modval[j] = attr[k]->attrvalue[j];
604 mods[i]->mod_values = modval;
607 return (mods);
609 free_memory:
610 freeModList(mods);
611 if (mapping)
612 __s_api_free2dArray(mapping);
614 return (NULL);
618 static LDAPMod **
619 __s_api_makeModList(
620 const char *service,
621 const ns_ldap_attr_t * const *attr,
622 const int mod_op,
623 const int flags)
625 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
626 int count = 0;
628 if (aptr == NULL)
629 return (NULL);
631 /* count number of attributes */
632 while (*aptr++)
633 count++;
635 return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
638 static void
639 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
641 if (*entry != NULL) {
642 __ns_ldap_freeEntry(*entry);
643 *entry = NULL;
645 if (*rdn != NULL) {
646 free(*rdn);
647 *rdn = NULL;
652 * This state machine performs one or more LDAP add/delete/modify
653 * operations to configured LDAP servers.
655 static int
656 write_state_machine(
657 int ldap_op,
658 char *dn,
659 LDAPMod **mods,
660 const ns_cred_t *cred,
661 const int flags,
662 ns_ldap_error_t ** errorp)
664 ConnectionID connectionId = -1;
665 Connection *conp = NULL;
666 LDAPMessage *res;
667 char *target_dn = NULL;
668 char errstr[MAXERROR];
669 int rc = NS_LDAP_SUCCESS;
670 int return_rc = NS_LDAP_SUCCESS;
671 int followRef = FALSE;
672 int target_dn_allocated = FALSE;
673 int len;
674 int msgid;
675 int Errno;
676 boolean_t from_get_lderrno = B_FALSE;
677 int always = 1;
678 char *err, *errmsg = NULL;
679 /* referrals returned by the LDAP operation */
680 char **referrals = NULL;
682 * list of referrals used by the state machine, built from
683 * the referrals variable above
685 ns_referral_info_t *ref_list = NULL;
686 /* current referral */
687 ns_referral_info_t *current_ref = NULL;
688 ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
689 int do_not_fail_if_new_pwd_reqd = 0;
690 ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD;
691 int passwd_mgmt = 0;
692 int i = 0;
693 int ldap_error;
694 int nopasswd_acct_mgmt = 0;
695 ns_conn_user_t *conn_user = NULL;
697 while (always) {
698 switch (state) {
699 case W_EXIT:
700 /* return the MT connection and free the conn user */
701 if (conn_user != NULL) {
702 if (conn_user->use_mt_conn == B_TRUE) {
703 if (conn_user->ns_error != NULL) {
704 *errorp = conn_user->ns_error;
705 conn_user->ns_error = NULL;
706 return_rc = conn_user->ns_rc;
708 if (conn_user->conn_mt != NULL)
709 __s_api_conn_mt_return(
710 conn_user);
712 __s_api_conn_user_free(conn_user);
715 if (connectionId > -1)
716 DropConnection(connectionId, NS_LDAP_NEW_CONN);
717 if (ref_list)
718 __s_api_deleteRefInfo(ref_list);
719 if (target_dn && target_dn_allocated)
720 free(target_dn);
721 return (return_rc);
722 case W_INIT:
723 /* see if need to follow referrals */
724 rc = __s_api_toFollowReferrals(flags,
725 &followRef, errorp);
726 if (rc != NS_LDAP_SUCCESS) {
727 return_rc = rc;
728 new_state = W_ERROR;
729 break;
731 len = strlen(dn);
732 if (dn[len-1] == COMMATOK)
733 rc = __s_api_append_default_basedn(
734 dn, &target_dn, &target_dn_allocated,
735 errorp);
736 else
737 target_dn = dn;
738 if (rc != NS_LDAP_SUCCESS) {
739 return_rc = rc;
740 new_state = W_ERROR;
742 else
743 new_state = GET_CONNECTION;
744 break;
745 case GET_CONNECTION:
746 /* identify self as a write user */
747 conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE,
748 NULL, B_FALSE);
749 rc = __s_api_getConnection(NULL,
750 flags, cred, &connectionId, &conp, errorp,
751 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
752 conn_user);
755 * If password control attached
756 * in *errorp,
757 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
758 * free the error structure (we do not need
759 * the password management info).
760 * Reset rc to NS_LDAP_SUCCESS.
762 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
763 (void) __ns_ldap_freeError(errorp);
764 *errorp = NULL;
765 rc = NS_LDAP_SUCCESS;
768 if (rc != NS_LDAP_SUCCESS) {
769 return_rc = rc;
770 new_state = W_ERROR;
771 break;
773 if (followRef)
774 new_state = SELECT_OPERATION_ASYNC;
775 else
776 new_state = SELECT_OPERATION_SYNC;
777 break;
778 case SELECT_OPERATION_SYNC:
779 if (ldap_op == LDAP_REQ_ADD)
780 new_state = DO_ADD_SYNC;
781 else if (ldap_op == LDAP_REQ_DELETE)
782 new_state = DO_DELETE_SYNC;
783 else if (ldap_op == LDAP_REQ_MODIFY)
784 new_state = DO_MODIFY_SYNC;
785 break;
786 case SELECT_OPERATION_ASYNC:
787 if (ldap_op == LDAP_REQ_ADD)
788 new_state = DO_ADD_ASYNC;
789 else if (ldap_op == LDAP_REQ_DELETE)
790 new_state = DO_DELETE_ASYNC;
791 else if (ldap_op == LDAP_REQ_MODIFY)
792 new_state = DO_MODIFY_ASYNC;
793 break;
794 case DO_ADD_SYNC:
795 rc = ldap_add_ext_s(conp->ld, target_dn,
796 mods, NULL, NULL);
797 new_state = GET_RESULT_SYNC;
798 break;
799 case DO_DELETE_SYNC:
800 rc = ldap_delete_ext_s(conp->ld, target_dn,
801 NULL, NULL);
802 new_state = GET_RESULT_SYNC;
803 break;
804 case DO_MODIFY_SYNC:
805 rc = ldap_modify_ext_s(conp->ld, target_dn,
806 mods, NULL, NULL);
807 new_state = GET_RESULT_SYNC;
808 break;
809 case DO_ADD_ASYNC:
810 rc = ldap_add_ext(conp->ld, target_dn,
811 mods, NULL, NULL, &msgid);
812 new_state = GET_RESULT_ASYNC;
813 break;
814 case DO_DELETE_ASYNC:
815 rc = ldap_delete_ext(conp->ld, target_dn,
816 NULL, NULL, &msgid);
817 new_state = GET_RESULT_ASYNC;
818 break;
819 case DO_MODIFY_ASYNC:
820 rc = ldap_modify_ext(conp->ld, target_dn,
821 mods, NULL, NULL, &msgid);
822 new_state = GET_RESULT_ASYNC;
823 break;
824 case GET_RESULT_SYNC:
825 if (rc != LDAP_SUCCESS) {
826 Errno = rc;
827 (void) ldap_get_lderrno(conp->ld,
828 NULL, &errmsg);
831 * No need to deal with the error message if
832 * it's an empty string.
834 if (errmsg != NULL && *errmsg == '\0')
835 errmsg = NULL;
837 if (errmsg != NULL) {
839 * ldap_get_lderrno does not expect
840 * errmsg to be freed after use, while
841 * ldap_parse_result below does, so set
842 * a flag to indicate source.
844 from_get_lderrno = B_TRUE;
847 new_state = W_LDAP_ERROR;
848 } else {
849 return_rc = NS_LDAP_SUCCESS;
850 new_state = W_EXIT;
852 break;
853 case GET_RESULT_ASYNC:
854 rc = ldap_result(conp->ld, msgid, 1,
855 NULL, &res);
856 /* if no server response, set Errno */
857 if (rc == -1) {
858 (void) ldap_get_option(conp->ld,
859 LDAP_OPT_ERROR_NUMBER, &Errno);
860 new_state = W_LDAP_ERROR;
861 break;
863 if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY ||
864 rc == LDAP_RES_DELETE) {
865 new_state = PARSE_RESULT;
866 break;
867 } else {
868 return_rc = rc;
869 new_state = W_ERROR;
871 break;
872 case PARSE_RESULT:
874 * need Errno, referrals, error msg,
875 * and the last "1" is to free
876 * the result (res)
878 rc = ldap_parse_result(conp->ld, res, &Errno,
879 NULL, &errmsg, &referrals, NULL, 1);
881 * free errmsg if it is an empty string
883 if (errmsg && *errmsg == '\0') {
884 ldap_memfree(errmsg);
885 errmsg = NULL;
888 * If we received referral data, process
889 * it if:
890 * - we are configured to follow referrals
891 * - and not already in referral mode (to keep
892 * consistency with search_state_machine()
893 * which follows 1 level of referrals only;
894 * see proc_result_referrals() and
895 * proc_search_references().
897 if (Errno == LDAP_REFERRAL && followRef && !ref_list) {
898 for (i = 0; referrals[i] != NULL; i++) {
899 /* add to referral list */
900 rc = __s_api_addRefInfo(&ref_list,
901 referrals[i], NULL, NULL, NULL,
902 conp->ld);
903 if (rc != NS_LDAP_SUCCESS) {
904 __s_api_deleteRefInfo(ref_list);
905 ref_list = NULL;
906 break;
909 ldap_value_free(referrals);
910 if (ref_list == NULL) {
911 if (rc != NS_LDAP_MEMORY)
912 rc = NS_LDAP_INTERNAL;
913 return_rc = rc;
914 new_state = W_ERROR;
915 } else {
916 new_state = GET_REFERRAL_CONNECTION;
917 current_ref = ref_list;
919 if (errmsg) {
920 ldap_memfree(errmsg);
921 errmsg = NULL;
923 break;
925 if (Errno != LDAP_SUCCESS) {
926 new_state = W_LDAP_ERROR;
927 } else {
928 return_rc = NS_LDAP_SUCCESS;
929 new_state = W_EXIT;
931 break;
932 case GET_REFERRAL_CONNECTION:
934 * since we are starting over,
935 * discard the old error info
937 return_rc = NS_LDAP_SUCCESS;
938 if (*errorp)
939 (void) __ns_ldap_freeError(errorp);
940 if (connectionId > -1)
941 DropConnection(connectionId, NS_LDAP_NEW_CONN);
943 /* set it up to use a referral connection */
944 if (conn_user != NULL) {
946 * If an MT connection is being used,
947 * return it to the pool.
949 if (conn_user->conn_mt != NULL)
950 __s_api_conn_mt_return(conn_user);
952 conn_user->referral = B_TRUE;
954 rc = __s_api_getConnection(current_ref->refHost,
955 0, cred, &connectionId, &conp, errorp,
956 do_not_fail_if_new_pwd_reqd,
957 nopasswd_acct_mgmt, conn_user);
960 * If password control attached
961 * in errorp,
962 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
963 * free the error structure (we do not need
964 * the password management info).
965 * Reset rc to NS_LDAP_SUCCESS.
967 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
968 (void) __ns_ldap_freeError(errorp);
969 *errorp = NULL;
970 rc = NS_LDAP_SUCCESS;
973 if (rc != NS_LDAP_SUCCESS) {
974 return_rc = rc;
976 * If current referral is not
977 * available for some reason,
978 * try next referral in the list.
979 * Get LDAP error code from errorp.
981 if (*errorp != NULL) {
982 ns_write_state_t get_ref =
983 GET_REFERRAL_CONNECTION;
985 ldap_error = (*errorp)->status;
986 if (ldap_error == LDAP_BUSY ||
987 ldap_error == LDAP_UNAVAILABLE ||
988 ldap_error ==
989 LDAP_UNWILLING_TO_PERFORM ||
990 ldap_error == LDAP_CONNECT_ERROR ||
991 ldap_error == LDAP_SERVER_DOWN) {
992 current_ref = current_ref->next;
993 if (current_ref == NULL) {
994 /* no more referral to follow */
995 new_state = W_ERROR;
996 } else
997 new_state = get_ref;
999 * free errorp before going to
1000 * next referral
1002 (void) __ns_ldap_freeError(
1003 errorp);
1004 *errorp = NULL;
1005 break;
1008 * free errorp before going to W_ERROR
1010 (void) __ns_ldap_freeError(errorp);
1011 *errorp = NULL;
1013 /* else, exit */
1014 __s_api_deleteRefInfo(ref_list);
1015 ref_list = NULL;
1016 new_state = W_ERROR;
1017 if (conn_user != NULL)
1018 conn_user->referral = B_FALSE;
1019 break;
1021 /* target DN may changed due to referrals */
1022 if (current_ref->refDN) {
1023 if (target_dn && target_dn_allocated) {
1024 free(target_dn);
1025 target_dn = NULL;
1026 target_dn_allocated = FALSE;
1028 target_dn = current_ref->refDN;
1030 new_state = SELECT_OPERATION_SYNC;
1031 break;
1032 case W_LDAP_ERROR:
1034 * map error code and error message
1035 * to password status if necessary.
1036 * This is to see if password updates
1037 * failed due to password policy or
1038 * password syntax checking.
1040 if (errmsg) {
1042 * check if server supports
1043 * password management
1045 passwd_mgmt =
1046 __s_api_contain_passwd_control_oid(
1047 conp->controls);
1048 if (passwd_mgmt)
1049 pwd_status =
1050 __s_api_set_passwd_status(
1051 Errno, errmsg);
1053 * free only if not returned by ldap_get_lderrno
1055 if (!from_get_lderrno)
1056 ldap_memfree(errmsg);
1057 errmsg = NULL;
1058 from_get_lderrno = B_FALSE;
1061 (void) snprintf(errstr, sizeof (errstr),
1062 "%s", ldap_err2string(Errno));
1063 err = strdup(errstr);
1064 if (pwd_status != NS_PASSWD_GOOD) {
1065 MKERROR_PWD_MGMT(*errorp, Errno, err,
1066 pwd_status, 0, 0);
1067 } else {
1068 MKERROR(LOG_INFO, *errorp, Errno, err, 0);
1070 if (conn_user != NULL &&
1071 (Errno == LDAP_SERVER_DOWN ||
1072 Errno == LDAP_CONNECT_ERROR)) {
1073 __s_api_conn_mt_close(conn_user, Errno, errorp);
1075 return_rc = NS_LDAP_INTERNAL;
1076 new_state = W_EXIT;
1077 break;
1078 case W_ERROR:
1079 default:
1080 (void) sprintf(errstr,
1081 gettext("Internal write State machine exit"
1082 " (state = %d, rc = %d)."),
1083 err_state, return_rc);
1084 err = strdup(errstr);
1085 MKERROR(LOG_WARNING, *errorp, return_rc, err, 0);
1086 new_state = W_EXIT;
1087 break;
1090 if (new_state == W_ERROR)
1091 err_state = state;
1093 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
1094 __s_api_conn_mt_close(conn_user, 0, NULL);
1095 new_state = W_EXIT;
1098 state = new_state;
1102 * should never be here, the next line is to eliminating
1103 * lint message
1105 return (NS_LDAP_INTERNAL);
1109 /*ARGSUSED*/
1111 __ns_ldap_addAttr(
1112 const char *service,
1113 const char *dn,
1114 const ns_ldap_attr_t * const *attr,
1115 const ns_cred_t *cred,
1116 const int flags,
1117 ns_ldap_error_t ** errorp)
1119 LDAPMod **mods;
1120 int rc = 0;
1122 #ifdef DEBUG
1123 (void) fprintf(stderr, "__ns_ldap_addAttr START\n");
1124 #endif
1125 *errorp = NULL;
1127 /* Sanity check */
1128 if ((attr == NULL) || (*attr == NULL) ||
1129 (dn == NULL) || (cred == NULL))
1130 return (NS_LDAP_INVALID_PARAM);
1132 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1133 if (mods == NULL) {
1134 return (NS_LDAP_MEMORY);
1137 rc = write_state_machine(LDAP_REQ_MODIFY,
1138 (char *)dn, mods, cred, flags, errorp);
1139 freeModList(mods);
1141 return (rc);
1145 /*ARGSUSED*/
1147 __ns_ldap_delAttr(
1148 const char *service,
1149 const char *dn,
1150 const ns_ldap_attr_t * const *attr,
1151 const ns_cred_t *cred,
1152 const int flags,
1153 ns_ldap_error_t ** errorp)
1155 LDAPMod **mods;
1156 int rc = 0;
1158 #ifdef DEBUG
1159 (void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1160 #endif
1161 *errorp = NULL;
1163 /* Sanity check */
1164 if ((attr == NULL) || (*attr == NULL) ||
1165 (dn == NULL) || (cred == NULL))
1166 return (NS_LDAP_INVALID_PARAM);
1168 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1169 if (mods == NULL) {
1170 return (NS_LDAP_MEMORY);
1173 rc = write_state_machine(LDAP_REQ_MODIFY,
1174 (char *)dn, mods, cred, flags, errorp);
1176 freeModList(mods);
1177 return (rc);
1180 /* Retrieve the admin bind password from the configuration, if allowed. */
1181 static int
1182 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
1184 void **paramVal = NULL;
1185 int rc, ldaprc;
1186 char *modparamVal = NULL;
1189 * For GSSAPI/Kerberos, host credential is used, no need to get
1190 * admin bind password
1192 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
1193 return (NS_LDAP_SUCCESS);
1196 * Retrieve admin bind password.
1197 * The admin bind password is available
1198 * only in the ldap_cachemgr process as
1199 * they are not exposed outside of that
1200 * process.
1202 paramVal = NULL;
1203 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1204 &paramVal, errorp)) != NS_LDAP_SUCCESS)
1205 return (ldaprc);
1206 if (paramVal == NULL || *paramVal == NULL) {
1207 rc = NS_LDAP_CONFIG;
1208 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
1209 gettext("Admin bind password not configured"));
1210 if (*errorp == NULL)
1211 rc = NS_LDAP_MEMORY;
1212 return (rc);
1214 modparamVal = dvalue((char *)*paramVal);
1215 (void) memset(*paramVal, 0, strlen((char *)*paramVal));
1216 (void) __ns_ldap_freeParam(&paramVal);
1217 if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
1218 free(modparamVal);
1219 rc = NS_LDAP_CONFIG;
1220 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
1221 gettext("bind password not valid"));
1222 if (*errorp == NULL)
1223 rc = NS_LDAP_MEMORY;
1224 return (rc);
1227 cred->cred.unix_cred.passwd = modparamVal;
1228 return (NS_LDAP_SUCCESS);
1231 boolean_t
1232 __ns_ldap_is_shadow_update_enabled(void)
1234 int **enable_shadow = NULL;
1235 ns_ldap_error_t *errorp = NULL;
1237 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1238 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1239 if (errorp)
1240 (void) __ns_ldap_freeError(&errorp);
1241 return (B_FALSE);
1243 if ((enable_shadow != NULL && *enable_shadow != NULL) &&
1244 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
1245 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1246 return (B_TRUE);
1248 if (enable_shadow != NULL)
1249 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1250 return (B_FALSE);
1254 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
1255 * on the LDAP server. 'service' indicates the type of database entries
1256 * to modify. When the Native LDAP client is configured with 'shadow update
1257 * enabled', Shadowshadow(4) entries can only be modified by privileged users.
1258 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
1259 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
1260 * for performing the LDAP modify operation. ldap_cachemgr would call
1261 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
1262 * to identify itself, so that admin credential would be obtained and
1263 * the actual LDAP modify operation be done.
1265 /*ARGSUSED*/
1267 __ns_ldap_repAttr(
1268 const char *service,
1269 const char *dn,
1270 const ns_ldap_attr_t * const *attr,
1271 const ns_cred_t *cred,
1272 const int flags,
1273 ns_ldap_error_t ** errorp)
1275 LDAPMod **mods;
1276 int rc = 0;
1277 boolean_t priv;
1278 boolean_t shadow_update_enabled = B_FALSE;
1280 #ifdef DEBUG
1281 (void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1282 #endif
1283 *errorp = NULL;
1285 /* Sanity check */
1286 if (attr == NULL || *attr == NULL || dn == NULL)
1287 return (NS_LDAP_INVALID_PARAM);
1289 /* Privileged shadow modify? */
1290 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
1291 strcmp(service, "shadow") == 0) {
1293 /* Shadow update enabled ? If not, error out */
1294 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
1295 if (!shadow_update_enabled) {
1296 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
1297 gettext("Shadow Update is not enabled"));
1298 return (NS_LDAP_CONFIG);
1301 /* privileged shadow modify requires euid 0 or all zone privs */
1302 priv = (geteuid() == 0);
1303 if (!priv) {
1304 priv_set_t *ps = priv_allocset(); /* caller */
1305 priv_set_t *zs; /* zone */
1307 (void) getppriv(PRIV_EFFECTIVE, ps);
1308 zs = priv_str_to_set("zone", ",", NULL);
1309 priv = priv_isequalset(ps, zs);
1310 priv_freeset(ps);
1311 priv_freeset(zs);
1313 if (!priv)
1314 return (NS_LDAP_OP_FAILED);
1316 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
1317 return (rc);
1320 if (cred == NULL)
1321 return (NS_LDAP_INVALID_PARAM);
1324 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
1325 * ldap_cachemgr. We need to get the admin cred to do work.
1326 * If the caller is not ldap_cachemgr, but use the service
1327 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
1328 * as the admin cred is not available to the caller.
1330 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
1331 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
1332 NS_LDAP_SUCCESS)
1333 return (rc);
1336 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1337 if (mods == NULL)
1338 return (NS_LDAP_MEMORY);
1340 rc = write_state_machine(LDAP_REQ_MODIFY,
1341 (char *)dn, mods, cred, flags, errorp);
1343 freeModList(mods);
1344 return (rc);
1347 /*ARGSUSED*/
1349 __ns_ldap_addEntry(
1350 const char *service,
1351 const char *dn,
1352 const ns_ldap_entry_t *entry,
1353 const ns_cred_t *cred,
1354 const int flags,
1355 ns_ldap_error_t ** errorp)
1357 char *new_dn = NULL;
1358 LDAPMod **mods = NULL;
1359 const ns_ldap_attr_t * const *attr;
1360 int nAttr = 0;
1361 int rc = 0;
1363 #ifdef DEBUG
1364 (void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1365 #endif
1367 if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1368 return (NS_LDAP_INVALID_PARAM);
1369 *errorp = NULL;
1371 /* Construct array of LDAPMod representing attributes of new entry. */
1373 nAttr = entry->attr_count;
1374 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1375 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1376 nAttr, flags);
1377 if (mods == NULL) {
1378 return (NS_LDAP_MEMORY);
1381 rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1382 if (rc != NS_LDAP_SUCCESS) {
1383 freeModList(mods);
1384 return (rc);
1387 rc = write_state_machine(LDAP_REQ_ADD,
1388 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1390 free(new_dn);
1391 freeModList(mods);
1392 return (rc);
1396 /*ARGSUSED*/
1398 __ns_ldap_delEntry(
1399 const char *service,
1400 const char *dn,
1401 const ns_cred_t *cred,
1402 const int flags,
1403 ns_ldap_error_t ** errorp)
1405 int rc;
1407 #ifdef DEBUG
1408 (void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1409 #endif
1410 if ((dn == NULL) || (cred == NULL))
1411 return (NS_LDAP_INVALID_PARAM);
1413 *errorp = NULL;
1415 rc = write_state_machine(LDAP_REQ_DELETE,
1416 (char *)dn, NULL, cred, flags, errorp);
1418 return (rc);
1422 * Add Typed Entry Helper routines
1426 * Add Typed Entry Conversion routines
1429 static int
1430 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1432 ns_ldap_attr_t *a;
1433 char *v;
1435 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1436 if (a == NULL)
1437 return (NS_LDAP_MEMORY);
1438 a->attrname = strdup(attrname);
1439 if (a->attrname == NULL)
1440 return (NS_LDAP_MEMORY);
1441 a->attrvalue = (char **)calloc(1, sizeof (char **));
1442 if (a->attrvalue == NULL)
1443 return (NS_LDAP_MEMORY);
1444 a->value_count = 1;
1445 a->attrvalue[0] = NULL;
1446 v = strdup(value);
1447 if (v == NULL)
1448 return (NS_LDAP_MEMORY);
1449 a->attrvalue[0] = v;
1450 e->attr_pair[e->attr_count] = a;
1451 e->attr_count++;
1452 return (NS_LDAP_SUCCESS);
1455 static int
1456 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1458 ns_ldap_attr_t *a;
1459 char *v;
1460 char **av;
1461 int i, j;
1463 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1464 if (a == NULL)
1465 return (NS_LDAP_MEMORY);
1466 a->attrname = strdup(attrname);
1467 if (a->attrname == NULL)
1468 return (NS_LDAP_MEMORY);
1470 for (i = 0, av = argv; *av != NULL; av++, i++)
1473 a->attrvalue = (char **)calloc(i, sizeof (char *));
1475 if (a->attrvalue == NULL)
1476 return (NS_LDAP_MEMORY);
1478 a->value_count = i;
1479 for (j = 0; j < i; j++) {
1480 v = strdup(argv[j]);
1481 if (v == NULL)
1482 return (NS_LDAP_MEMORY);
1483 a->attrvalue[j] = v;
1485 e->attr_pair[e->attr_count] = a;
1486 e->attr_count++;
1487 return (NS_LDAP_SUCCESS);
1490 static ns_ldap_entry_t *
1491 __s_mk_entry(char **objclass, int max_attr)
1493 ns_ldap_entry_t *e;
1494 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1495 if (e == NULL)
1496 return (NULL);
1497 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1498 e->attr_pair = (ns_ldap_attr_t **)
1499 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1500 if (e->attr_pair == NULL) {
1501 free(e);
1502 return (NULL);
1504 e->attr_count = 0;
1505 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1506 free(e->attr_pair);
1507 free(e);
1508 return (NULL);
1510 return (e);
1515 * Conversion: passwd
1516 * Input format: struct passwd
1517 * Exported objectclass: posixAccount
1519 static int
1520 __s_cvt_passwd(const void *data, char **rdn,
1521 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1523 ns_ldap_entry_t *e;
1524 int rc;
1525 char trdn[RDNSIZE];
1526 /* routine specific */
1527 struct passwd *ptr;
1528 int max_attr = 9;
1529 char ibuf[10];
1530 static char *oclist[] = {
1531 "posixAccount",
1532 "shadowAccount",
1533 "account",
1534 "top",
1535 NULL
1538 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1539 return (NS_LDAP_OP_FAILED);
1540 *entry = e = __s_mk_entry(oclist, max_attr);
1541 if (e == NULL)
1542 return (NS_LDAP_MEMORY);
1544 /* Convert the structure */
1545 ptr = (struct passwd *)data;
1547 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
1548 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
1549 __ns_ldap_freeEntry(e);
1550 *entry = NULL;
1551 return (NS_LDAP_INVALID_PARAM);
1554 /* Create an appropriate rdn */
1555 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1556 *rdn = strdup(trdn);
1557 if (*rdn == NULL) {
1558 __ns_ldap_freeEntry(e);
1559 *entry = NULL;
1560 return (NS_LDAP_MEMORY);
1563 /* Error check the data and add the attributes */
1564 rc = __s_add_attr(e, "uid", ptr->pw_name);
1565 if (rc != NS_LDAP_SUCCESS) {
1566 __s_cvt_freeEntryRdn(entry, rdn);
1567 return (rc);
1569 rc = __s_add_attr(e, "cn", ptr->pw_name);
1570 if (rc != NS_LDAP_SUCCESS) {
1571 __s_cvt_freeEntryRdn(entry, rdn);
1572 return (rc);
1575 if (ptr->pw_passwd != NULL &&
1576 ptr->pw_passwd[0] != '\0') {
1577 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1578 if (rc != NS_LDAP_SUCCESS) {
1579 __s_cvt_freeEntryRdn(entry, rdn);
1580 return (rc);
1584 (void) sprintf(ibuf, "%u", ptr->pw_uid);
1585 rc = __s_add_attr(e, "uidNumber", ibuf);
1586 if (rc != NS_LDAP_SUCCESS) {
1587 __s_cvt_freeEntryRdn(entry, rdn);
1588 return (rc);
1591 (void) sprintf(ibuf, "%u", ptr->pw_gid);
1592 rc = __s_add_attr(e, "gidNumber", ibuf);
1593 if (rc != NS_LDAP_SUCCESS) {
1594 __s_cvt_freeEntryRdn(entry, rdn);
1595 return (rc);
1597 if (ptr->pw_gecos != NULL &&
1598 ptr->pw_gecos[0] != '\0') {
1599 rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1600 if (rc != NS_LDAP_SUCCESS) {
1601 __s_cvt_freeEntryRdn(entry, rdn);
1602 return (rc);
1606 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1607 if (rc != NS_LDAP_SUCCESS) {
1608 __s_cvt_freeEntryRdn(entry, rdn);
1609 return (rc);
1611 if (ptr->pw_shell != NULL &&
1612 ptr->pw_shell[0] != '\0') {
1613 rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1614 if (rc != NS_LDAP_SUCCESS) {
1615 __s_cvt_freeEntryRdn(entry, rdn);
1616 return (rc);
1620 return (NS_LDAP_SUCCESS);
1624 * escape_str function escapes special characters in str and
1625 * copies to escstr string.
1627 * return 0 for successful
1628 * 1 for fail
1630 static int escape_str(char *escstr, char *str)
1632 int index = 0;
1634 while ((*str != '\0') && (index < (RDNSIZE - 1))) {
1635 if (*str == '+' || *str == ';' || *str == '>' ||
1636 *str == '<' || *str == ',' || *str == '"' ||
1637 *str == '\\' || *str == '=' ||
1638 (*str == '#' && index == 0)) {
1639 *escstr++ = '\\';
1640 *escstr++ = *str++;
1641 index += 2;
1642 } else {
1643 *escstr++ = *str++;
1644 index++;
1648 if (*str == '\0') {
1649 *escstr = '\0';
1650 return (0);
1651 } else {
1652 return (1);
1657 * Conversion: project
1658 * Input format: struct project
1659 * Exported objectclass: SolarisProject
1661 static int
1662 __s_cvt_project(const void *data, char **rdn,
1663 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1665 ns_ldap_entry_t *e;
1666 int rc;
1667 char trdn[RDNSIZE];
1669 /* routine specific */
1670 struct project *ptr;
1671 int max_attr = 9;
1672 char ibuf[11];
1673 static char *oclist[] = {
1674 "SolarisProject",
1675 "top",
1676 NULL
1679 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1680 return (NS_LDAP_OP_FAILED);
1682 *entry = e = __s_mk_entry(oclist, max_attr);
1683 if (e == NULL)
1684 return (NS_LDAP_MEMORY);
1686 /* Convert the structure */
1687 ptr = (struct project *)data;
1689 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
1690 __ns_ldap_freeEntry(e);
1691 *entry = NULL;
1692 return (NS_LDAP_INVALID_PARAM);
1695 /* Create an appropriate rdn */
1696 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
1697 *rdn = strdup(trdn);
1698 if (*rdn == NULL) {
1699 __ns_ldap_freeEntry(e);
1700 *entry = NULL;
1701 return (NS_LDAP_MEMORY);
1704 /* Error check the data and add the attributes */
1706 /* Project name */
1707 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
1708 if (rc != NS_LDAP_SUCCESS) {
1709 __s_cvt_freeEntryRdn(entry, rdn);
1710 return (rc);
1714 * Project ID:
1715 * ibuf is 11 chars big, which should be enough for string
1716 * representation of 32bit number + nul-car
1718 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
1719 __s_cvt_freeEntryRdn(entry, rdn);
1720 return (NS_LDAP_INVALID_PARAM);
1722 rc = __s_add_attr(e, "SolarisProjectID", ibuf);
1723 if (rc != NS_LDAP_SUCCESS) {
1724 __s_cvt_freeEntryRdn(entry, rdn);
1725 return (rc);
1728 /* Comment/Description */
1729 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
1730 rc = __s_add_attr(e, "description", ptr->pj_comment);
1731 if (rc != NS_LDAP_SUCCESS) {
1732 __s_cvt_freeEntryRdn(entry, rdn);
1733 return (rc);
1737 /* Attributes */
1738 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
1739 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
1740 if (rc != NS_LDAP_SUCCESS) {
1741 __s_cvt_freeEntryRdn(entry, rdn);
1742 return (rc);
1746 /* Users */
1747 if (ptr->pj_users != NULL) {
1748 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
1749 if (rc != NS_LDAP_SUCCESS) {
1750 __s_cvt_freeEntryRdn(entry, rdn);
1751 return (rc);
1755 /* Groups */
1756 if (ptr->pj_groups != NULL) {
1757 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
1758 if (rc != NS_LDAP_SUCCESS) {
1759 __s_cvt_freeEntryRdn(entry, rdn);
1760 return (rc);
1766 return (NS_LDAP_SUCCESS);
1769 * Conversion: shadow
1770 * Input format: struct shadow
1771 * Exported objectclass: shadowAccount
1773 static int
1774 __s_cvt_shadow(const void *data, char **rdn,
1775 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1777 ns_ldap_entry_t *e;
1778 int rc;
1779 char trdn[RDNSIZE];
1780 /* routine specific */
1781 struct spwd *ptr;
1782 int max_attr = 10;
1783 char ibuf[10];
1784 static char *oclist[] = {
1785 "posixAccount",
1786 "shadowAccount",
1787 "account",
1788 "top",
1789 NULL
1792 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1793 return (NS_LDAP_OP_FAILED);
1794 *entry = e = __s_mk_entry(oclist, max_attr);
1795 if (e == NULL)
1796 return (NS_LDAP_MEMORY);
1798 /* Convert the structure */
1799 ptr = (struct spwd *)data;
1801 if (ptr->sp_namp == NULL) {
1802 __ns_ldap_freeEntry(e);
1803 *entry = NULL;
1804 return (NS_LDAP_INVALID_PARAM);
1807 /* Create an appropriate rdn */
1808 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1809 *rdn = strdup(trdn);
1810 if (*rdn == NULL) {
1811 __ns_ldap_freeEntry(e);
1812 *entry = NULL;
1813 return (NS_LDAP_MEMORY);
1816 /* Error check the data and add the attributes */
1817 rc = __s_add_attr(e, "uid", ptr->sp_namp);
1818 if (rc != NS_LDAP_SUCCESS) {
1819 __s_cvt_freeEntryRdn(entry, rdn);
1820 return (rc);
1823 if (ptr->sp_pwdp == NULL) {
1824 __s_cvt_freeEntryRdn(entry, rdn);
1825 return (NS_LDAP_INVALID_PARAM);
1826 } else {
1827 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1828 if (rc != NS_LDAP_SUCCESS) {
1829 __s_cvt_freeEntryRdn(entry, rdn);
1830 return (rc);
1833 if (ptr->sp_lstchg >= 0) {
1834 (void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1835 rc = __s_add_attr(e, "shadowLastChange", ibuf);
1836 if (rc != NS_LDAP_SUCCESS) {
1837 __s_cvt_freeEntryRdn(entry, rdn);
1838 return (rc);
1841 if (ptr->sp_min >= 0) {
1842 (void) sprintf(ibuf, "%d", ptr->sp_min);
1843 rc = __s_add_attr(e, "shadowMin", ibuf);
1844 if (rc != NS_LDAP_SUCCESS) {
1845 __s_cvt_freeEntryRdn(entry, rdn);
1846 return (rc);
1849 if (ptr->sp_max >= 0) {
1850 (void) sprintf(ibuf, "%d", ptr->sp_max);
1851 rc = __s_add_attr(e, "shadowMax", ibuf);
1852 if (rc != NS_LDAP_SUCCESS) {
1853 __s_cvt_freeEntryRdn(entry, rdn);
1854 return (rc);
1857 if (ptr->sp_warn >= 0) {
1858 (void) sprintf(ibuf, "%d", ptr->sp_warn);
1859 rc = __s_add_attr(e, "shadowWarning", ibuf);
1860 if (rc != NS_LDAP_SUCCESS) {
1861 __s_cvt_freeEntryRdn(entry, rdn);
1862 return (rc);
1865 if (ptr->sp_inact >= 0) {
1866 (void) sprintf(ibuf, "%d", ptr->sp_inact);
1867 rc = __s_add_attr(e, "shadowInactive", ibuf);
1868 if (rc != NS_LDAP_SUCCESS) {
1869 __s_cvt_freeEntryRdn(entry, rdn);
1870 return (rc);
1873 if (ptr->sp_expire >= 0) {
1874 (void) sprintf(ibuf, "%d", ptr->sp_expire);
1875 rc = __s_add_attr(e, "shadowExpire", ibuf);
1876 if (rc != NS_LDAP_SUCCESS) {
1877 __s_cvt_freeEntryRdn(entry, rdn);
1878 return (rc);
1881 (void) sprintf(ibuf, "%d", ptr->sp_flag);
1882 rc = __s_add_attr(e, "shadowFlag", ibuf);
1883 if (rc != NS_LDAP_SUCCESS) {
1884 __s_cvt_freeEntryRdn(entry, rdn);
1885 return (rc);
1888 return (NS_LDAP_SUCCESS);
1893 * Conversion: group
1894 * Input format: struct group
1895 * Exported objectclass: posixGroup
1897 static int
1898 __s_cvt_group(const void *data, char **rdn,
1899 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1901 ns_ldap_entry_t *e;
1902 int rc;
1903 char trdn[RDNSIZE];
1904 /* routine specific */
1905 struct group *ptr;
1906 int i, j, k;
1907 char **nm, **lm;
1908 int max_attr = 4;
1909 char ibuf[10];
1910 static char *oclist[] = {
1911 "posixGroup",
1912 "top",
1913 NULL
1916 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1917 return (NS_LDAP_OP_FAILED);
1918 *entry = e = __s_mk_entry(oclist, max_attr);
1919 if (e == NULL)
1920 return (NS_LDAP_MEMORY);
1922 /* Convert the structure */
1923 ptr = (struct group *)data;
1925 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
1926 __ns_ldap_freeEntry(e);
1927 *entry = NULL;
1928 return (NS_LDAP_INVALID_PARAM);
1931 /* Create an appropriate rdn */
1932 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1933 *rdn = strdup(trdn);
1934 if (*rdn == NULL) {
1935 __ns_ldap_freeEntry(e);
1936 *entry = NULL;
1937 return (NS_LDAP_MEMORY);
1940 /* Error check the data and add the attributes */
1941 rc = __s_add_attr(e, "cn", ptr->gr_name);
1942 if (rc != NS_LDAP_SUCCESS) {
1943 __s_cvt_freeEntryRdn(entry, rdn);
1944 return (rc);
1947 (void) sprintf(ibuf, "%u", ptr->gr_gid);
1948 rc = __s_add_attr(e, "gidNumber", ibuf);
1949 if (rc != NS_LDAP_SUCCESS) {
1950 __s_cvt_freeEntryRdn(entry, rdn);
1951 return (rc);
1953 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1954 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1955 if (rc != NS_LDAP_SUCCESS) {
1956 __s_cvt_freeEntryRdn(entry, rdn);
1957 return (rc);
1961 if (ptr->gr_mem && ptr->gr_mem[0]) {
1962 lm = ptr->gr_mem;
1963 for (i = 0; *lm; i++, lm++)
1965 lm = ptr->gr_mem;
1966 nm = (char **)calloc(i+2, sizeof (char *));
1967 if (nm == NULL) {
1968 __s_cvt_freeEntryRdn(entry, rdn);
1969 return (NS_LDAP_MEMORY);
1971 for (j = 0; j < i; j++) {
1972 nm[j] = strdup(lm[j]);
1973 if (nm[j] == NULL) {
1974 for (k = 0; k < j; k++)
1975 free(nm[k]);
1976 free(nm);
1977 __s_cvt_freeEntryRdn(entry, rdn);
1978 return (NS_LDAP_MEMORY);
1981 rc = __s_add_attrlist(e, "memberUid", nm);
1982 for (j = 0; j < i; j++) {
1983 free(nm[j]);
1985 free(nm);
1986 nm = NULL;
1987 if (rc != NS_LDAP_SUCCESS) {
1988 __s_cvt_freeEntryRdn(entry, rdn);
1989 return (rc);
1993 return (NS_LDAP_SUCCESS);
1997 * Conversion: hosts
1998 * Input format: struct hostent
1999 * Exported objectclass: ipHost
2001 static int
2002 __s_cvt_hosts(const void *data, char **rdn,
2003 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2005 ns_ldap_entry_t *e;
2006 int rc;
2007 char trdn[RDNSIZE];
2008 /* routine specific */
2009 struct hostent *ptr;
2010 int max_attr = 6;
2011 int i, j, k;
2012 char **nm, **lm;
2013 static char *oclist[] = {
2014 "ipHost",
2015 "device",
2016 "top",
2017 NULL
2020 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2021 return (NS_LDAP_OP_FAILED);
2022 *entry = e = __s_mk_entry(oclist, max_attr);
2023 if (e == NULL)
2024 return (NS_LDAP_MEMORY);
2026 /* Convert the structure */
2027 ptr = (struct hostent *)data;
2029 if (ptr->h_name == NULL ||
2030 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') {
2031 __ns_ldap_freeEntry(e);
2032 *entry = NULL;
2033 return (NS_LDAP_INVALID_PARAM);
2036 /* Create an appropriate rdn */
2037 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
2038 ptr->h_name, ptr->h_addr_list[0]);
2039 *rdn = strdup(trdn);
2040 if (*rdn == NULL) {
2041 __ns_ldap_freeEntry(e);
2042 *entry = NULL;
2043 return (NS_LDAP_MEMORY);
2046 /* Error check the data and add the attributes */
2047 if (ptr->h_aliases && ptr->h_aliases[0]) {
2048 lm = ptr->h_aliases;
2050 * If there is a description, 'i' will contain
2051 * the index of the description in the aliases list
2053 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
2055 lm = ptr->h_aliases;
2056 nm = (char **)calloc(i+2, sizeof (char *));
2057 if (nm == NULL) {
2058 __s_cvt_freeEntryRdn(entry, rdn);
2059 return (NS_LDAP_MEMORY);
2061 nm[0] = ptr->h_name;
2062 for (j = 0; j < i; j++)
2063 nm[j+1] = ptr->h_aliases[j];
2065 rc = __s_add_attrlist(e, "cn", nm);
2067 if (rc != NS_LDAP_SUCCESS) {
2068 __s_cvt_freeEntryRdn(entry, rdn);
2069 free(nm);
2070 return (rc);
2073 if (lm[i] && lm[i][0] == '#') {
2074 nm[0] = &(lm[i][1]);
2075 nm[1] = NULL;
2076 rc = __s_add_attrlist(e, "description", nm);
2078 free(nm);
2079 nm = NULL;
2080 if (rc != NS_LDAP_SUCCESS) {
2081 __s_cvt_freeEntryRdn(entry, rdn);
2082 return (rc);
2084 } else {
2085 rc = __s_add_attr(e, "cn", ptr->h_name);
2086 if (rc != NS_LDAP_SUCCESS) {
2087 __s_cvt_freeEntryRdn(entry, rdn);
2088 return (rc);
2092 if (ptr->h_addr_list && ptr->h_addr_list[0]) {
2093 lm = ptr->h_addr_list;
2094 for (i = 0; *lm; i++, lm++)
2096 lm = ptr->h_addr_list;
2097 nm = (char **)calloc(i+2, sizeof (char *));
2098 if (nm == NULL) {
2099 __s_cvt_freeEntryRdn(entry, rdn);
2100 return (NS_LDAP_MEMORY);
2102 for (j = 0; j < i; j++) {
2103 nm[j] = strdup(lm[j]);
2104 if (nm[j] == NULL) {
2105 for (k = 0; k < j; k++)
2106 free(nm[k]);
2107 free(nm);
2108 __s_cvt_freeEntryRdn(entry, rdn);
2109 return (NS_LDAP_MEMORY);
2112 rc = __s_add_attrlist(e, "ipHostNumber", nm);
2113 for (j = 0; j < i; j++) {
2114 free(nm[j]);
2116 free(nm);
2117 nm = NULL;
2118 if (rc != NS_LDAP_SUCCESS) {
2119 __s_cvt_freeEntryRdn(entry, rdn);
2120 return (rc);
2122 } else {
2123 __s_cvt_freeEntryRdn(entry, rdn);
2124 return (NS_LDAP_INVALID_PARAM);
2127 return (NS_LDAP_SUCCESS);
2131 * Conversion: rpc
2132 * Input format: struct rpcent
2133 * Exported objectclass: oncRpc
2135 static int
2136 __s_cvt_rpc(const void *data, char **rdn,
2137 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2139 ns_ldap_entry_t *e;
2140 int rc;
2141 char trdn[RDNSIZE];
2142 /* routine specific */
2143 struct rpcent *ptr;
2144 int max_attr = 3;
2145 int i, j;
2146 char **nm;
2147 char ibuf[10];
2148 static char *oclist[] = {
2149 "oncRpc",
2150 "top",
2151 NULL
2154 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2155 return (NS_LDAP_OP_FAILED);
2156 *entry = e = __s_mk_entry(oclist, max_attr);
2157 if (e == NULL)
2158 return (NS_LDAP_MEMORY);
2160 /* Convert the structure */
2161 ptr = (struct rpcent *)data;
2163 if (ptr->r_name == NULL || ptr->r_number < 0) {
2164 __ns_ldap_freeEntry(e);
2165 *entry = NULL;
2166 return (NS_LDAP_INVALID_PARAM);
2169 /* Create an appropriate rdn */
2170 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
2171 *rdn = strdup(trdn);
2172 if (*rdn == NULL) {
2173 __ns_ldap_freeEntry(e);
2174 *entry = NULL;
2175 return (NS_LDAP_MEMORY);
2178 /* Error check the data and add the attributes */
2179 if (ptr->r_aliases && ptr->r_aliases[0]) {
2180 nm = ptr->r_aliases;
2181 for (i = 0; *nm; i++, nm++)
2183 nm = (char **)calloc(i+2, sizeof (char *));
2184 if (nm == NULL) {
2185 __s_cvt_freeEntryRdn(entry, rdn);
2186 return (NS_LDAP_MEMORY);
2188 nm[0] = ptr->r_name;
2189 for (j = 0; j < i; j++)
2190 nm[j+1] = ptr->r_aliases[j];
2192 rc = __s_add_attrlist(e, "cn", nm);
2193 free(nm);
2194 nm = NULL;
2195 if (rc != NS_LDAP_SUCCESS) {
2196 __s_cvt_freeEntryRdn(entry, rdn);
2197 return (rc);
2199 } else {
2200 rc = __s_add_attr(e, "cn", ptr->r_name);
2201 if (rc != NS_LDAP_SUCCESS) {
2202 __s_cvt_freeEntryRdn(entry, rdn);
2203 return (rc);
2207 if (ptr->r_number >= 0) {
2208 (void) sprintf(ibuf, "%d", ptr->r_number);
2209 rc = __s_add_attr(e, "oncRpcNumber", ibuf);
2210 if (rc != NS_LDAP_SUCCESS) {
2211 __s_cvt_freeEntryRdn(entry, rdn);
2212 return (rc);
2216 return (NS_LDAP_SUCCESS);
2221 * Conversion: protocols
2222 * Input format: struct protoent
2223 * Exported objectclass: ipProtocol
2225 static int
2226 __s_cvt_protocols(const void *data, char **rdn,
2227 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2229 ns_ldap_entry_t *e;
2230 int rc;
2231 char trdn[RDNSIZE];
2232 /* routine specific */
2233 struct protoent *ptr;
2234 int max_attr = 3;
2235 int i, j;
2236 char ibuf[10];
2237 char **nm;
2238 static char *oclist[] = {
2239 "ipProtocol",
2240 "top",
2241 NULL
2244 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2245 return (NS_LDAP_OP_FAILED);
2246 *entry = e = __s_mk_entry(oclist, max_attr);
2247 if (e == NULL)
2248 return (NS_LDAP_MEMORY);
2250 /* Convert the structure */
2251 ptr = (struct protoent *)data;
2253 if (ptr->p_name == NULL || ptr->p_proto < 0) {
2254 __ns_ldap_freeEntry(e);
2255 *entry = NULL;
2256 return (NS_LDAP_INVALID_PARAM);
2259 /* Create an appropriate rdn */
2260 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
2261 *rdn = strdup(trdn);
2262 if (*rdn == NULL) {
2263 __ns_ldap_freeEntry(e);
2264 *entry = NULL;
2265 return (NS_LDAP_MEMORY);
2268 /* Error check the data and add the attributes */
2269 if (ptr->p_aliases && ptr->p_aliases[0]) {
2270 nm = ptr->p_aliases;
2271 for (i = 0; *nm; i++, nm++)
2273 nm = (char **)calloc(i+2, sizeof (char *));
2274 if (nm == NULL) {
2275 __s_cvt_freeEntryRdn(entry, rdn);
2276 return (NS_LDAP_MEMORY);
2278 nm[0] = ptr->p_name;
2279 for (j = 0; j < i; j++)
2280 nm[j+1] = ptr->p_aliases[j];
2282 rc = __s_add_attrlist(e, "cn", nm);
2283 free(nm);
2284 nm = NULL;
2285 if (rc != NS_LDAP_SUCCESS) {
2286 __s_cvt_freeEntryRdn(entry, rdn);
2287 return (rc);
2289 } else {
2290 rc = __s_add_attr(e, "cn", ptr->p_name);
2291 if (rc != NS_LDAP_SUCCESS) {
2292 __s_cvt_freeEntryRdn(entry, rdn);
2293 return (rc);
2297 (void) sprintf(ibuf, "%d", ptr->p_proto);
2298 rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
2299 if (rc != NS_LDAP_SUCCESS) {
2300 __s_cvt_freeEntryRdn(entry, rdn);
2301 return (rc);
2304 return (NS_LDAP_SUCCESS);
2309 * Conversion: services
2310 * Input format: struct servent
2311 * Exported objectclass: ipService
2313 static int
2314 __s_cvt_services(const void *data, char **rdn,
2315 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2317 ns_ldap_entry_t *e;
2318 int rc;
2319 char trdn[RDNSIZE];
2320 char esc_str[RDNSIZE];
2321 /* routine specific */
2322 struct servent *ptr;
2323 int max_attr = 4;
2324 int i, j;
2325 char ibuf[10];
2326 char **nm;
2327 static char *oclist[] = {
2328 "ipService",
2329 "top",
2330 NULL
2333 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2334 return (NS_LDAP_OP_FAILED);
2335 *entry = e = __s_mk_entry(oclist, max_attr);
2336 if (e == NULL)
2337 return (NS_LDAP_MEMORY);
2339 /* Convert the structure */
2340 ptr = (struct servent *)data;
2342 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') {
2343 __ns_ldap_freeEntry(e);
2344 *entry = NULL;
2345 return (NS_LDAP_INVALID_PARAM);
2349 * Escape special characters in service name.
2351 if (escape_str(esc_str, ptr->s_name) != 0) {
2352 __ns_ldap_freeEntry(e);
2353 *entry = NULL;
2354 return (NS_LDAP_INVALID_PARAM);
2357 /* Create an appropriate rdn */
2358 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
2359 esc_str, ptr->s_proto);
2361 *rdn = strdup(trdn);
2362 if (*rdn == NULL) {
2363 __ns_ldap_freeEntry(e);
2364 *entry = NULL;
2365 return (NS_LDAP_MEMORY);
2368 /* Error check the data and add the attributes */
2369 if (ptr->s_aliases && ptr->s_aliases[0]) {
2370 nm = ptr->s_aliases;
2371 for (i = 0; *nm; i++, nm++)
2373 nm = (char **)calloc(i+2, sizeof (char *));
2374 if (nm == NULL) {
2375 __s_cvt_freeEntryRdn(entry, rdn);
2376 return (NS_LDAP_MEMORY);
2378 nm[0] = ptr->s_name;
2379 for (j = 0; j < i; j++)
2380 nm[j+1] = ptr->s_aliases[j];
2382 rc = __s_add_attrlist(e, "cn", nm);
2383 free(nm);
2384 nm = NULL;
2385 if (rc != NS_LDAP_SUCCESS) {
2386 __s_cvt_freeEntryRdn(entry, rdn);
2387 return (rc);
2389 } else {
2390 rc = __s_add_attr(e, "cn", ptr->s_name);
2391 if (rc != NS_LDAP_SUCCESS) {
2392 __s_cvt_freeEntryRdn(entry, rdn);
2393 return (rc);
2397 (void) sprintf(ibuf, "%d", ptr->s_port);
2398 rc = __s_add_attr(e, "ipServicePort", ibuf);
2399 if (rc != NS_LDAP_SUCCESS) {
2400 __s_cvt_freeEntryRdn(entry, rdn);
2401 return (rc);
2403 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
2404 if (rc != NS_LDAP_SUCCESS) {
2405 __s_cvt_freeEntryRdn(entry, rdn);
2406 return (rc);
2409 return (NS_LDAP_SUCCESS);
2413 * Conversion: networks
2414 * Input format: struct netent
2415 * Exported objectclass: ipNetwork
2417 static int
2418 __s_cvt_networks(const void *data, char **rdn,
2419 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2421 ns_ldap_entry_t *e;
2422 int rc;
2423 char trdn[RDNSIZE];
2424 /* routine specific */
2425 struct netent *ptr;
2426 int max_attr = 4;
2427 int i, j;
2428 char cp[64];
2429 char **nm;
2430 static char *oclist[] = {
2431 "ipNetwork",
2432 "top",
2433 NULL
2436 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2437 return (NS_LDAP_OP_FAILED);
2438 *entry = e = __s_mk_entry(oclist, max_attr);
2439 if (e == NULL)
2440 return (NS_LDAP_MEMORY);
2442 /* Convert the structure */
2443 ptr = (struct netent *)data;
2445 if (ptr->n_name == NULL || ptr->n_net == 0) {
2446 __ns_ldap_freeEntry(e);
2447 *entry = NULL;
2448 return (NS_LDAP_INVALID_PARAM);
2451 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2452 (ptr->n_net & 0xFF000000) >> 24,
2453 (ptr->n_net & 0x00FF0000) >> 16,
2454 (ptr->n_net & 0x0000FF00) >> 8,
2455 (ptr->n_net & 0x000000FF));
2457 /* Create an appropriate rdn */
2458 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2459 *rdn = strdup(trdn);
2460 if (*rdn == NULL) {
2461 __ns_ldap_freeEntry(e);
2462 *entry = NULL;
2463 return (NS_LDAP_MEMORY);
2466 /* Error check the data and add the attributes */
2467 if (ptr->n_aliases && ptr->n_aliases[0]) {
2468 nm = ptr->n_aliases;
2469 for (i = 0; *nm; i++, nm++)
2471 nm = (char **)calloc(i+2, sizeof (char *));
2472 if (nm == NULL) {
2473 __s_cvt_freeEntryRdn(entry, rdn);
2474 return (NS_LDAP_MEMORY);
2476 nm[0] = ptr->n_name;
2477 for (j = 0; j < i; j++)
2478 nm[j+1] = ptr->n_aliases[j];
2480 rc = __s_add_attrlist(e, "cn", nm);
2481 free(nm);
2482 nm = NULL;
2483 if (rc != NS_LDAP_SUCCESS) {
2484 __s_cvt_freeEntryRdn(entry, rdn);
2485 return (rc);
2487 } else {
2488 rc = __s_add_attr(e, "cn", ptr->n_name);
2489 if (rc != NS_LDAP_SUCCESS) {
2490 __s_cvt_freeEntryRdn(entry, rdn);
2491 return (rc);
2495 rc = __s_add_attr(e, "ipNetworkNumber", cp);
2496 if (rc != NS_LDAP_SUCCESS) {
2497 __s_cvt_freeEntryRdn(entry, rdn);
2498 return (rc);
2501 return (NS_LDAP_SUCCESS);
2505 * Conversion: netmasks
2506 * Input format: struct _ns_netmasks
2507 * Exported objectclass: ipNetwork
2509 static int
2510 __s_cvt_netmasks(const void *data, char **rdn,
2511 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2513 ns_ldap_entry_t *e;
2514 int rc;
2515 char trdn[RDNSIZE];
2516 /* routine specific */
2517 struct _ns_netmasks *ptr;
2518 int max_attr = 4;
2519 static char *oclist[] = {
2520 "ipNetwork",
2521 "top",
2522 NULL
2525 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2526 return (NS_LDAP_OP_FAILED);
2527 *entry = e = __s_mk_entry(oclist, max_attr);
2528 if (e == NULL)
2529 return (NS_LDAP_MEMORY);
2531 /* Convert the structure */
2532 ptr = (struct _ns_netmasks *)data;
2534 if (ptr->netnumber == NULL) {
2535 __ns_ldap_freeEntry(e);
2536 *entry = NULL;
2537 return (NS_LDAP_INVALID_PARAM);
2540 /* Create an appropriate rdn */
2541 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2542 *rdn = strdup(trdn);
2543 if (*rdn == NULL) {
2544 __ns_ldap_freeEntry(e);
2545 *entry = NULL;
2546 return (NS_LDAP_MEMORY);
2549 /* Error check the data and add the attributes */
2550 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2551 if (rc != NS_LDAP_SUCCESS) {
2552 __s_cvt_freeEntryRdn(entry, rdn);
2553 return (rc);
2556 if (ptr->netmask != '\0') {
2557 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2558 if (rc != NS_LDAP_SUCCESS) {
2559 __s_cvt_freeEntryRdn(entry, rdn);
2560 return (rc);
2564 return (NS_LDAP_SUCCESS);
2568 * Conversion: netgroups
2569 * Input format: struct _ns_netgroups
2570 * Exported objectclass: nisNetgroup
2572 static int
2573 __s_cvt_netgroups(const void *data, char **rdn,
2574 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2576 ns_ldap_entry_t *e;
2577 int rc;
2578 char trdn[RDNSIZE];
2579 /* routine specific */
2580 struct _ns_netgroups *ptr;
2581 int max_attr = 6;
2582 int i, j;
2583 char **nm;
2584 static char *oclist[] = {
2585 "nisNetgroup",
2586 "top",
2587 NULL
2590 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2591 return (NS_LDAP_OP_FAILED);
2592 *entry = e = __s_mk_entry(oclist, max_attr);
2593 if (e == NULL)
2594 return (NS_LDAP_MEMORY);
2596 /* Convert the structure */
2597 ptr = (struct _ns_netgroups *)data;
2599 if (ptr->name == NULL) {
2600 __ns_ldap_freeEntry(e);
2601 *entry = NULL;
2602 return (NS_LDAP_INVALID_PARAM);
2605 /* Create an appropriate rdn */
2606 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2607 *rdn = strdup(trdn);
2608 if (*rdn == NULL) {
2609 __ns_ldap_freeEntry(e);
2610 *entry = NULL;
2611 return (NS_LDAP_MEMORY);
2614 if (ptr->name != '\0') {
2615 rc = __s_add_attr(e, "cn", ptr->name);
2616 if (rc != NS_LDAP_SUCCESS) {
2617 __s_cvt_freeEntryRdn(entry, rdn);
2618 return (rc);
2622 /* Error check the data and add the attributes */
2623 if (ptr->triplet && ptr->triplet[0]) {
2624 nm = ptr->triplet;
2625 for (i = 0; *nm; i++, nm++)
2627 nm = (char **)calloc(i+2, sizeof (char *));
2628 if (nm == NULL) {
2629 __s_cvt_freeEntryRdn(entry, rdn);
2630 return (NS_LDAP_MEMORY);
2632 for (j = 0; j < i; j++)
2633 nm[j] = ptr->triplet[j];
2635 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
2636 free(nm);
2637 nm = NULL;
2638 if (rc != NS_LDAP_SUCCESS) {
2639 __s_cvt_freeEntryRdn(entry, rdn);
2640 return (rc);
2643 if (ptr->netgroup && ptr->netgroup[0]) {
2644 nm = ptr->netgroup;
2645 for (i = 0; *nm; i++, nm++)
2647 nm = (char **)calloc(i+2, sizeof (char *));
2648 if (nm == NULL) {
2649 __s_cvt_freeEntryRdn(entry, rdn);
2650 return (NS_LDAP_MEMORY);
2652 for (j = 0; j < i; j++)
2653 nm[j] = ptr->netgroup[j];
2655 rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
2656 free(nm);
2657 nm = NULL;
2658 if (rc != NS_LDAP_SUCCESS) {
2659 __s_cvt_freeEntryRdn(entry, rdn);
2660 return (rc);
2663 return (NS_LDAP_SUCCESS);
2666 * Conversion: bootparams
2667 * Input format: struct _ns_bootp
2668 * Exported objectclass: bootableDevice, device
2670 static int
2671 __s_cvt_bootparams(const void *data, char **rdn,
2672 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2674 ns_ldap_entry_t *e;
2675 int rc;
2676 char trdn[RDNSIZE];
2677 /* routine specific */
2678 struct _ns_bootp *ptr;
2679 int max_attr = 4;
2680 int i, j;
2681 char **nm;
2682 static char *oclist[] = {
2683 "bootableDevice",
2684 "device",
2685 "top",
2686 NULL
2689 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2690 return (NS_LDAP_OP_FAILED);
2691 *entry = e = __s_mk_entry(oclist, max_attr);
2692 if (e == NULL)
2693 return (NS_LDAP_MEMORY);
2695 /* Convert the structure */
2696 ptr = (struct _ns_bootp *)data;
2698 if (ptr->name == NULL) {
2699 __ns_ldap_freeEntry(e);
2700 *entry = NULL;
2701 return (NS_LDAP_INVALID_PARAM);
2704 /* Create an appropriate rdn */
2705 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2706 *rdn = strdup(trdn);
2707 if (*rdn == NULL) {
2708 __ns_ldap_freeEntry(e);
2709 *entry = NULL;
2710 return (NS_LDAP_MEMORY);
2713 if (ptr->name != '\0') {
2714 rc = __s_add_attr(e, "cn", ptr->name);
2715 if (rc != NS_LDAP_SUCCESS) {
2716 __s_cvt_freeEntryRdn(entry, rdn);
2717 return (rc);
2721 /* Error check the data and add the attributes */
2722 if (ptr->param && ptr->param[0]) {
2723 nm = ptr->param;
2724 for (i = 0; *nm; i++, nm++)
2726 nm = (char **)calloc(i+2, sizeof (char *));
2727 if (nm == NULL) {
2728 __s_cvt_freeEntryRdn(entry, rdn);
2729 return (NS_LDAP_MEMORY);
2731 for (j = 0; j < i; j++)
2732 nm[j] = ptr->param[j];
2734 rc = __s_add_attrlist(e, "bootParameter", nm);
2735 free(nm);
2736 nm = NULL;
2737 if (rc != NS_LDAP_SUCCESS) {
2738 __s_cvt_freeEntryRdn(entry, rdn);
2739 return (rc);
2743 return (NS_LDAP_SUCCESS);
2747 * Conversion: ethers
2748 * Input format: struct _ns_ethers
2749 * Exported objectclass: ieee802Device, device
2751 static int
2752 __s_cvt_ethers(const void *data, char **rdn,
2753 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2755 ns_ldap_entry_t *e;
2756 int rc;
2757 char trdn[RDNSIZE];
2758 /* routine specific */
2759 struct _ns_ethers *ptr;
2760 int max_attr = 4;
2761 static char *oclist[] = {
2762 "ieee802Device",
2763 "device",
2764 "top",
2765 NULL
2768 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2769 return (NS_LDAP_OP_FAILED);
2770 *entry = e = __s_mk_entry(oclist, max_attr);
2771 if (e == NULL)
2772 return (NS_LDAP_MEMORY);
2774 /* Convert the structure */
2775 ptr = (struct _ns_ethers *)data;
2777 if (ptr->name == NULL || ptr->ether == '\0') {
2778 __ns_ldap_freeEntry(e);
2779 *entry = NULL;
2780 return (NS_LDAP_INVALID_PARAM);
2783 /* Create an appropriate rdn */
2784 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2785 *rdn = strdup(trdn);
2786 if (*rdn == NULL) {
2787 __ns_ldap_freeEntry(e);
2788 *entry = NULL;
2789 return (NS_LDAP_MEMORY);
2792 /* Error check the data and add the attributes */
2793 rc = __s_add_attr(e, "cn", ptr->name);
2794 if (rc != NS_LDAP_SUCCESS) {
2795 __s_cvt_freeEntryRdn(entry, rdn);
2796 return (rc);
2799 rc = __s_add_attr(e, "macAddress", ptr->ether);
2800 if (rc != NS_LDAP_SUCCESS) {
2801 __s_cvt_freeEntryRdn(entry, rdn);
2802 return (rc);
2805 return (NS_LDAP_SUCCESS);
2808 * This function is used when processing an ethers (objectclass: ieee802Device)
2809 * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2810 * already found in LDAP. Since both ethers and bootparams share the same
2811 * LDAP container, we want to check that the entry found in LDAP is:
2812 * - either the same entry (same cn, same objectclass): we don't do anything
2813 * in this case
2814 * - or an entry which does not have the objectclass we are interesting in:
2815 * in this case, we modify the existing entry by adding the relevant
2816 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2817 * from the attribute list previously computing by the relevant conversion
2818 * function.
2819 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams()
2820 * we know that there is only 1 more attribute today to add (macAddress
2821 * or bootParameter)
2823 #define _MAX_ATTR_ETHBOOTP 2
2824 static int
2825 modify_ethers_bootp(
2826 const char *service,
2827 const char *rdn,
2828 const char *fulldn,
2829 const ns_ldap_attr_t * const *attrlist,
2830 const ns_cred_t *cred,
2831 const int flags,
2832 ns_ldap_error_t **errorp)
2834 char filter[BUFSIZ];
2835 ns_ldap_result_t *resultp;
2836 int rc = 0;
2837 int i;
2838 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2839 ns_ldap_attr_t new_attrlist0;
2840 char *new_attrvalue0[1];
2841 const ns_ldap_attr_t * const *aptr = attrlist;
2842 ns_ldap_attr_t *aptr2;
2843 ns_ldap_error_t *new_errorp = NULL;
2845 if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2846 errorp == NULL || service == NULL)
2847 return (NS_LDAP_OP_FAILED);
2849 bzero(&new_attrlist, sizeof (new_attrlist));
2850 bzero(&new_attrlist0, sizeof (new_attrlist0));
2851 new_attrlist[0] = &new_attrlist0;
2852 new_attrlist[0]->attrvalue = new_attrvalue0;
2854 new_attrlist[0]->attrname = "objectclass";
2855 new_attrlist[0]->value_count = 1;
2856 if (strcasecmp(service, "ethers") == 0) {
2857 (void) snprintf(&filter[0], sizeof (filter),
2858 "(&(objectClass=ieee802Device)(%s))", rdn);
2859 new_attrlist[0]->attrvalue[0] = "ieee802Device";
2860 } else {
2861 (void) snprintf(&filter[0], sizeof (filter),
2862 "(&(objectClass=bootableDevice)(%s))", rdn);
2863 new_attrlist[0]->attrvalue[0] = "bootableDevice";
2866 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2867 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2868 NULL, NULL);
2870 switch (rc) {
2871 case NS_LDAP_SUCCESS:
2873 * entry already exists for this service
2874 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2876 rc = NS_LDAP_INTERNAL;
2877 break;
2878 case NS_LDAP_NOTFOUND:
2880 * entry not found with the given objectclasss but entry exists
2881 * hence add the relevant attribute (macAddress or bootparams).
2883 i = 1;
2884 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2885 /* aptr2 needed here to avoid lint warning */
2886 aptr2 = (ns_ldap_attr_t *)*aptr++;
2887 if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2888 (strcasecmp(aptr2->attrname,
2889 "objectclass") != 0)) {
2890 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
2894 if (i != _MAX_ATTR_ETHBOOTP) {
2895 /* we haven't found all expected attributes */
2896 rc = NS_LDAP_OP_FAILED;
2897 break;
2900 aptr = (const ns_ldap_attr_t * const *) new_attrlist;
2901 /* clean errorp first */
2902 (void) __ns_ldap_freeError(errorp);
2903 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2904 errorp);
2905 break;
2906 default:
2908 * unexpected error happenned
2909 * returning relevant error
2911 (void) __ns_ldap_freeError(errorp);
2912 *errorp = new_errorp;
2913 break;
2916 return (rc);
2920 * Conversion: publickey
2921 * Input format: struct _ns_pubkey
2922 * Exported objectclass: NisKeyObject
2924 static int
2925 __s_cvt_publickey(const void *data, char **rdn,
2926 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2928 ns_ldap_entry_t *e;
2929 int rc;
2930 char trdn[RDNSIZE];
2931 /* routine specific */
2932 struct _ns_pubkey *ptr;
2933 int max_attr = 3;
2934 static char *oclist[] = {
2935 "NisKeyObject",
2936 NULL
2939 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2940 return (NS_LDAP_OP_FAILED);
2941 *entry = e = __s_mk_entry(oclist, max_attr);
2942 if (e == NULL)
2943 return (NS_LDAP_MEMORY);
2945 /* Convert the structure */
2946 ptr = (struct _ns_pubkey *)data;
2948 if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') {
2949 __ns_ldap_freeEntry(e);
2950 *entry = NULL;
2951 return (NS_LDAP_INVALID_PARAM);
2954 /* Create an appropriate rdn */
2955 if (ptr->hostcred == NS_HOSTCRED_FALSE)
2956 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2957 else
2958 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2959 *rdn = strdup(trdn);
2960 if (*rdn == NULL) {
2961 __ns_ldap_freeEntry(e);
2962 *entry = NULL;
2963 return (NS_LDAP_MEMORY);
2966 /* Error check the data and add the attributes */
2968 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2969 if (rc != NS_LDAP_SUCCESS) {
2970 __s_cvt_freeEntryRdn(entry, rdn);
2971 return (rc);
2974 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2975 if (rc != NS_LDAP_SUCCESS) {
2976 __s_cvt_freeEntryRdn(entry, rdn);
2977 return (rc);
2980 return (NS_LDAP_SUCCESS);
2983 * Conversion: aliases
2984 * Input format: struct _ns_alias
2985 * Exported objectclass: mailGroup
2987 static int
2988 __s_cvt_aliases(const void *data, char **rdn,
2989 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2991 ns_ldap_entry_t *e;
2992 int rc;
2993 char trdn[RDNSIZE];
2994 /* routine specific */
2995 struct _ns_alias *ptr;
2996 int max_attr = 4;
2997 int i, j;
2998 char **nm;
2999 static char *oclist[] = {
3000 "mailGroup",
3001 "top",
3002 NULL
3005 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3006 return (NS_LDAP_OP_FAILED);
3007 *entry = e = __s_mk_entry(oclist, max_attr);
3008 if (e == NULL)
3009 return (NS_LDAP_MEMORY);
3011 /* Convert the structure */
3012 ptr = (struct _ns_alias *)data;
3014 if (ptr->alias == NULL) {
3015 __ns_ldap_freeEntry(e);
3016 *entry = NULL;
3017 return (NS_LDAP_INVALID_PARAM);
3020 /* Create an appropriate rdn */
3021 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
3022 *rdn = strdup(trdn);
3023 if (*rdn == NULL) {
3024 __ns_ldap_freeEntry(e);
3025 *entry = NULL;
3026 return (NS_LDAP_MEMORY);
3029 if (ptr->alias != '\0') {
3030 rc = __s_add_attr(e, "mail", (char *)ptr->alias);
3031 if (rc != NS_LDAP_SUCCESS) {
3032 __s_cvt_freeEntryRdn(entry, rdn);
3033 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->value == '\0' || ptr->mapname == '\0') {
3113 __ns_ldap_freeEntry(e);
3114 *entry = NULL;
3115 return (NS_LDAP_INVALID_PARAM);
3118 /* Create an appropriate rdn */
3119 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
3120 ptr->key);
3121 *rdn = strdup(trdn);
3122 if (*rdn == NULL) {
3123 __ns_ldap_freeEntry(e);
3124 *entry = NULL;
3125 return (NS_LDAP_MEMORY);
3128 if (ptr->key != '\0') {
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);
3137 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
3138 (char *)ptr->value);
3139 if (rc != NS_LDAP_SUCCESS) {
3140 __s_cvt_freeEntryRdn(entry, rdn);
3141 return (rc);
3145 * even for version 2, if automount is mapped to nisObject we
3146 * still need 'nisMapName' attribute
3148 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
3149 if (mappedschema && mappedschema[0] &&
3150 strcasecmp(mappedschema[0], "nisObject") == 0)
3151 version1 = 1;
3152 if (mappedschema)
3153 __s_api_free2dArray(mappedschema);
3155 if (version1) {
3156 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
3157 if (rc != NS_LDAP_SUCCESS) {
3158 __s_cvt_freeEntryRdn(entry, rdn);
3159 return (rc);
3163 return (NS_LDAP_SUCCESS);
3166 * Conversion: auth_attr
3167 * Input format: authstr_t
3168 * Exported objectclass: SolarisAuthAttr
3170 static int
3171 __s_cvt_authattr(const void *data, char **rdn,
3172 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3174 ns_ldap_entry_t *e;
3175 int rc;
3176 char trdn[RDNSIZE];
3177 /* routine specific */
3178 authstr_t *ptr;
3179 int max_attr = 6;
3180 static char *oclist[] = {
3181 "SolarisAuthAttr",
3182 "top",
3183 NULL
3186 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3187 return (NS_LDAP_OP_FAILED);
3189 *entry = e = __s_mk_entry(oclist, max_attr);
3190 if (e == NULL)
3191 return (NS_LDAP_MEMORY);
3193 /* Convert the structure */
3194 ptr = (authstr_t *)data;
3196 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3197 __ns_ldap_freeEntry(e);
3198 *entry = NULL;
3199 return (NS_LDAP_INVALID_PARAM);
3202 /* Create an appropriate rdn */
3203 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3204 *rdn = strdup(trdn);
3205 if (*rdn == NULL) {
3206 __ns_ldap_freeEntry(e);
3207 *entry = NULL;
3208 return (NS_LDAP_MEMORY);
3211 rc = __s_add_attr(e, "cn", ptr->name);
3212 if (rc != NS_LDAP_SUCCESS) {
3213 __s_cvt_freeEntryRdn(entry, rdn);
3214 return (rc);
3217 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3218 if (rc != NS_LDAP_SUCCESS) {
3219 __s_cvt_freeEntryRdn(entry, rdn);
3220 return (rc);
3223 if (ptr->res1 != NULL) {
3224 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3225 if (rc != NS_LDAP_SUCCESS) {
3226 __s_cvt_freeEntryRdn(entry, rdn);
3227 return (rc);
3231 if (ptr->res2 != NULL) {
3232 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3233 if (rc != NS_LDAP_SUCCESS) {
3234 __s_cvt_freeEntryRdn(entry, rdn);
3235 return (rc);
3239 if (ptr->short_desc != NULL) {
3240 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
3241 if (rc != NS_LDAP_SUCCESS) {
3242 __s_cvt_freeEntryRdn(entry, rdn);
3243 return (rc);
3247 if (ptr->long_desc != NULL) {
3248 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
3249 if (rc != NS_LDAP_SUCCESS) {
3250 __s_cvt_freeEntryRdn(entry, rdn);
3251 return (rc);
3255 return (NS_LDAP_SUCCESS);
3258 * Conversion: exec_attr
3259 * Input format: execstr_t
3260 * Exported objectclass: SolarisExecAttr
3262 static int
3263 __s_cvt_execattr(const void *data, char **rdn,
3264 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3266 ns_ldap_entry_t *e;
3267 int rc;
3268 char trdn[RDNSIZE];
3269 char esc_str[RDNSIZE];
3270 /* routine specific */
3271 execstr_t *ptr;
3272 int max_attr = 7;
3273 static char *oclist[] = {
3274 "SolarisExecAttr",
3275 "SolarisProfAttr",
3276 "top",
3277 NULL
3280 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3281 return (NS_LDAP_OP_FAILED);
3283 *entry = e = __s_mk_entry(oclist, max_attr);
3284 if (e == NULL)
3285 return (NS_LDAP_MEMORY);
3287 /* Convert the structure */
3288 ptr = (execstr_t *)data;
3290 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3291 ptr->policy == NULL || ptr->policy[0] == '\0' ||
3292 ptr->type == NULL || ptr->type[0] == '\0' ||
3293 ptr->id == NULL || ptr->id[0] == '\0') {
3294 __ns_ldap_freeEntry(e);
3295 *entry = NULL;
3296 return (NS_LDAP_INVALID_PARAM);
3300 * Escape special characters in ProfileID.
3302 if (escape_str(esc_str, ptr->id) != 0) {
3303 __ns_ldap_freeEntry(e);
3304 *entry = NULL;
3305 return (NS_LDAP_INVALID_PARAM);
3308 /* Create an appropriate rdn */
3309 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
3310 "+SolarisProfileType=%s+SolarisProfileId=%s",
3311 ptr->name, ptr->policy, ptr->type, esc_str);
3313 *rdn = strdup(trdn);
3314 if (*rdn == NULL) {
3315 __ns_ldap_freeEntry(e);
3316 *entry = NULL;
3317 return (NS_LDAP_MEMORY);
3320 rc = __s_add_attr(e, "cn", ptr->name);
3321 if (rc != NS_LDAP_SUCCESS) {
3322 __s_cvt_freeEntryRdn(entry, rdn);
3323 return (rc);
3326 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
3327 if (rc != NS_LDAP_SUCCESS) {
3328 __s_cvt_freeEntryRdn(entry, rdn);
3329 return (rc);
3332 rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
3333 if (rc != NS_LDAP_SUCCESS) {
3334 __s_cvt_freeEntryRdn(entry, rdn);
3335 return (rc);
3338 rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
3339 if (rc != NS_LDAP_SUCCESS) {
3340 __s_cvt_freeEntryRdn(entry, rdn);
3341 return (rc);
3344 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3345 if (rc != NS_LDAP_SUCCESS) {
3346 __s_cvt_freeEntryRdn(entry, rdn);
3347 return (rc);
3350 if (ptr->res1 != NULL) {
3351 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
3352 if (rc != NS_LDAP_SUCCESS) {
3353 __s_cvt_freeEntryRdn(entry, rdn);
3354 return (rc);
3358 if (ptr->res2 != NULL) {
3359 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
3360 if (rc != NS_LDAP_SUCCESS) {
3361 __s_cvt_freeEntryRdn(entry, rdn);
3362 return (rc);
3366 return (NS_LDAP_SUCCESS);
3369 * Conversion: prof_attr
3370 * Input format: profstr_t
3371 * Exported objectclass: SolarisProfAttr
3373 static int
3374 __s_cvt_profattr(const void *data, char **rdn,
3375 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3377 ns_ldap_entry_t *e;
3378 int rc;
3379 char trdn[RDNSIZE];
3380 /* routine specific */
3381 profstr_t *ptr;
3382 int max_attr = 5;
3383 static char *oclist[] = {
3384 "SolarisProfAttr",
3385 "top",
3386 NULL
3389 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3390 return (NS_LDAP_OP_FAILED);
3392 *entry = e = __s_mk_entry(oclist, max_attr);
3393 if (e == NULL)
3394 return (NS_LDAP_MEMORY);
3396 /* Convert the structure */
3397 ptr = (profstr_t *)data;
3399 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3400 __ns_ldap_freeEntry(e);
3401 *entry = NULL;
3402 return (NS_LDAP_INVALID_PARAM);
3405 /* Create an appropriate rdn */
3406 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3407 *rdn = strdup(trdn);
3408 if (*rdn == NULL) {
3409 __ns_ldap_freeEntry(e);
3410 *entry = NULL;
3411 return (NS_LDAP_MEMORY);
3414 rc = __s_add_attr(e, "cn", ptr->name);
3415 if (rc != NS_LDAP_SUCCESS) {
3416 __s_cvt_freeEntryRdn(entry, rdn);
3417 return (rc);
3420 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3421 if (rc != NS_LDAP_SUCCESS) {
3422 __s_cvt_freeEntryRdn(entry, rdn);
3423 return (rc);
3426 if (ptr->res1 != NULL) {
3427 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3428 if (rc != NS_LDAP_SUCCESS) {
3429 __s_cvt_freeEntryRdn(entry, rdn);
3430 return (rc);
3434 if (ptr->res2 != NULL) {
3435 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3436 if (rc != NS_LDAP_SUCCESS) {
3437 __s_cvt_freeEntryRdn(entry, rdn);
3438 return (rc);
3442 if (ptr->desc != NULL) {
3443 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3444 if (rc != NS_LDAP_SUCCESS) {
3445 __s_cvt_freeEntryRdn(entry, rdn);
3446 return (rc);
3450 return (NS_LDAP_SUCCESS);
3453 * Conversion: user_attr
3454 * Input format: userstr_t
3455 * Exported objectclass: SolarisUserAttr
3457 static int
3458 __s_cvt_userattr(const void *data, char **rdn,
3459 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3461 ns_ldap_entry_t *e;
3462 int rc;
3463 char trdn[RDNSIZE];
3464 /* routine specific */
3465 userstr_t *ptr;
3466 int max_attr = 5;
3467 static char *oclist[] = {
3468 "SolarisUserAttr",
3469 NULL
3472 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3473 return (NS_LDAP_OP_FAILED);
3475 *entry = e = __s_mk_entry(oclist, max_attr);
3476 if (e == NULL)
3477 return (NS_LDAP_MEMORY);
3479 /* Convert the structure */
3480 ptr = (userstr_t *)data;
3482 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3483 ptr->attr == NULL) {
3484 __ns_ldap_freeEntry(e);
3485 *entry = NULL;
3486 return (NS_LDAP_INVALID_PARAM);
3489 /* Create an appropriate rdn */
3490 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3491 *rdn = strdup(trdn);
3492 if (*rdn == NULL) {
3493 __ns_ldap_freeEntry(e);
3494 *entry = NULL;
3495 return (NS_LDAP_MEMORY);
3499 * SolarisUserAttr has no uid attribute
3502 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3503 if (rc != NS_LDAP_SUCCESS) {
3504 __s_cvt_freeEntryRdn(entry, rdn);
3505 return (rc);
3508 if (ptr->qualifier != NULL) {
3509 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3510 if (rc != NS_LDAP_SUCCESS) {
3511 __s_cvt_freeEntryRdn(entry, rdn);
3512 return (rc);
3516 if (ptr->res1 != NULL) {
3517 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3518 if (rc != NS_LDAP_SUCCESS) {
3519 __s_cvt_freeEntryRdn(entry, rdn);
3520 return (rc);
3524 if (ptr->res2 != NULL) {
3525 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3526 if (rc != NS_LDAP_SUCCESS) {
3527 __s_cvt_freeEntryRdn(entry, rdn);
3528 return (rc);
3532 return (NS_LDAP_SUCCESS);
3535 * Conversion: audit_user
3536 * Input format: au_user_str_t
3537 * Exported objectclass: SolarisAuditUser
3539 static int
3540 __s_cvt_audituser(const void *data, char **rdn,
3541 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3543 ns_ldap_entry_t *e;
3544 int rc;
3545 char trdn[RDNSIZE];
3546 /* routine specific */
3547 au_user_str_t *ptr;
3548 int max_attr = 3;
3549 static char *oclist[] = {
3550 "SolarisAuditUser",
3551 NULL
3554 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3555 return (NS_LDAP_OP_FAILED);
3557 *entry = e = __s_mk_entry(oclist, max_attr);
3558 if (e == NULL)
3559 return (NS_LDAP_MEMORY);
3561 /* Convert the structure */
3562 ptr = (au_user_str_t *)data;
3564 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
3565 __ns_ldap_freeEntry(e);
3566 *entry = NULL;
3567 return (NS_LDAP_INVALID_PARAM);
3570 /* Create an appropriate rdn */
3571 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
3572 *rdn = strdup(trdn);
3573 if (*rdn == NULL) {
3574 __ns_ldap_freeEntry(e);
3575 *entry = NULL;
3576 return (NS_LDAP_MEMORY);
3580 * Solaris AuditUser has no uid attribute
3583 if (ptr->au_always != NULL) {
3584 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
3585 if (rc != NS_LDAP_SUCCESS) {
3586 __s_cvt_freeEntryRdn(entry, rdn);
3587 return (rc);
3591 if (ptr->au_never != NULL) {
3592 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
3593 if (rc != NS_LDAP_SUCCESS) {
3594 __s_cvt_freeEntryRdn(entry, rdn);
3595 return (rc);
3599 return (NS_LDAP_SUCCESS);
3603 * Add Typed Entry Conversion data structures
3606 typedef struct __ns_cvt_type {
3607 const char *service;
3608 int flags;
3609 #define AE 1 /* alway add entries */
3610 int (*cvt_rtn)(const void *data,
3611 char **rdn,
3612 ns_ldap_entry_t **entry,
3613 ns_ldap_error_t **errorp);
3614 } __ns_cvt_type_t;
3616 static __ns_cvt_type_t __s_cvtlist[] = {
3617 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd },
3618 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group },
3619 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts },
3620 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts },
3621 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc },
3622 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols },
3623 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks },
3624 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups },
3625 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases },
3626 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services },
3627 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers },
3628 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow },
3629 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks },
3630 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams },
3631 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr },
3632 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr },
3633 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr },
3634 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr },
3635 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
3636 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
3637 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser },
3638 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project },
3639 { NULL, 0, NULL },
3643 * Add Typed Entry Routine
3646 /*ARGSUSED*/
3647 int __ns_ldap_addTypedEntry(
3648 const char *servicetype,
3649 const char *basedn,
3650 const void *data,
3651 const int create,
3652 const ns_cred_t *cred,
3653 const int flags,
3654 ns_ldap_error_t **errorp)
3656 char *rdn = NULL, *fulldn = NULL;
3657 void **paramVal = NULL;
3658 ns_ldap_entry_t *entry = NULL;
3659 const ns_ldap_attr_t *const *modattrlist;
3660 ns_ldap_search_desc_t **sdlist;
3661 char **dns = NULL;
3662 char trdn[RDNSIZE];
3663 char service[BUFSIZE];
3664 int rc = 0;
3665 int automount = 0;
3666 int i, s;
3668 rc = NS_LDAP_OP_FAILED;
3669 for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3670 if (__s_cvtlist[s].cvt_rtn == NULL)
3671 continue;
3672 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3673 break;
3674 /* Or, check if the servicetype is auto_ */
3675 if (strcmp(__s_cvtlist[s].service,
3676 NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3677 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3678 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3679 automount++;
3680 break;
3683 if (__s_cvtlist[s].service == NULL)
3684 return (rc);
3686 /* Convert the data */
3687 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3688 if (rc != NS_LDAP_SUCCESS) {
3689 __s_cvt_freeEntryRdn(&entry, &rdn);
3690 return (rc);
3692 if (rdn == NULL) {
3693 __ns_ldap_freeEntry(entry);
3694 return (NS_LDAP_OP_FAILED);
3697 if (strcmp(servicetype, "publickey") == 0) {
3698 struct _ns_pubkey *ptr;
3699 ptr = (struct _ns_pubkey *)data;
3700 if (ptr->hostcred == NS_HOSTCRED_TRUE)
3701 (void) strcpy(service, "hosts");
3702 else
3703 (void) strcpy(service, "passwd");
3704 } else
3705 (void) strcpy(service, servicetype);
3707 /* Create the Full DN */
3708 if (basedn == NULL) {
3709 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3710 &sdlist, errorp);
3711 if (rc != NS_LDAP_SUCCESS) {
3712 __s_cvt_freeEntryRdn(&entry, &rdn);
3713 return (rc);
3716 if (sdlist == NULL) {
3717 rc = __s_api_getDNs(&dns, service, errorp);
3718 if (rc != NS_LDAP_SUCCESS) {
3719 if (dns) {
3720 __s_api_free2dArray(dns);
3721 dns = NULL;
3723 __s_cvt_freeEntryRdn(&entry, &rdn);
3724 return (rc);
3726 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3727 __s_api_free2dArray(dns);
3728 } else {
3729 if (sdlist[0]->basedn) {
3730 (void) snprintf(trdn, RDNSIZE, "%s,%s",
3731 rdn, sdlist[0]->basedn);
3732 } else {
3733 __s_cvt_freeEntryRdn(&entry, &rdn);
3734 return (NS_LDAP_OP_FAILED);
3737 i = strlen(trdn) - 1;
3738 if (trdn[i] == COMMATOK) {
3739 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3740 &paramVal, errorp);
3741 if (rc != NS_LDAP_SUCCESS) {
3742 __s_cvt_freeEntryRdn(&entry, &rdn);
3743 return (rc);
3745 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3746 fulldn = (char *)calloc(i, 1);
3747 if (fulldn == NULL) {
3748 (void) __ns_ldap_freeParam(&paramVal);
3749 __s_cvt_freeEntryRdn(&entry, &rdn);
3750 return (NS_LDAP_MEMORY);
3752 (void) snprintf(fulldn, i, "%s%s", trdn,
3753 (char *)(paramVal[0]));
3754 (void) __ns_ldap_freeParam(&paramVal);
3755 } else {
3756 fulldn = strdup(trdn);
3757 if (fulldn == NULL) {
3758 __s_cvt_freeEntryRdn(&entry, &rdn);
3759 return (NS_LDAP_MEMORY);
3762 } else {
3763 i = strlen(rdn) + strlen(basedn) + 2;
3764 fulldn = (char *)calloc(i, 1);
3765 if (fulldn == NULL) {
3766 __s_cvt_freeEntryRdn(&entry, &rdn);
3767 return (NS_LDAP_MEMORY);
3769 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3772 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3773 /* Check to see if the entry exists already */
3774 /* May need to delete or update first */
3776 if (create != 1) {
3777 /* Modify the entry */
3779 * To add a shadow-like entry, the addTypedEntry function
3780 * would call __ns_ldap_repAttr first, and if server says
3781 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
3782 * This is to allow a netmask entry to be added even if the
3783 * base network entry is not in the directory. It would work
3784 * because the difference between the schema for the network
3785 * and netmask data contains only MAY attributes.
3787 * But for shadow data, the attributes do not have MUST
3788 * attributes the base entry needs, so if the __ns_ldap_addEntry
3789 * is executed, it would fail. The real reason, however, is that
3790 * the base entry did not exist. So returning
3791 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
3793 if ((__s_cvtlist[s].flags & AE) != 0)
3794 rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3795 cred, flags, errorp);
3796 else {
3797 rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3798 cred, flags, errorp);
3799 if (rc == NS_LDAP_INTERNAL && *errorp &&
3800 (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3801 (void) __ns_ldap_freeError(errorp);
3802 rc = __ns_ldap_addEntry(service, fulldn,
3803 entry, cred, flags, errorp);
3804 if (rc == NS_LDAP_INTERNAL && *errorp &&
3805 (*errorp)->status ==
3806 LDAP_OBJECT_CLASS_VIOLATION)
3807 (*errorp)->status = LDAP_NO_SUCH_OBJECT;
3810 } else {
3811 /* Add the entry */
3812 rc = __ns_ldap_addEntry(service, fulldn, entry,
3813 cred, flags, errorp);
3814 if (rc == NS_LDAP_INTERNAL && *errorp &&
3815 (*errorp)->status == LDAP_ALREADY_EXISTS &&
3816 ((strcmp(service, "ethers") == 0) ||
3817 (strcmp(service, "bootparams") == 0))) {
3818 rc = modify_ethers_bootp(service, rdn, fulldn,
3819 modattrlist, cred, flags, errorp);
3823 /* Free up entry created by conversion routine */
3824 free(fulldn);
3825 __s_cvt_freeEntryRdn(&entry, &rdn);
3826 return (rc);
3831 * Append the default base dn to the dn
3832 * when it ends with ','.
3833 * e.g.
3834 * SSD = service:ou=foo,
3837 __s_api_append_default_basedn(
3838 const char *dn,
3839 char **new_dn,
3840 int *allocated,
3841 ns_ldap_error_t **errp) {
3843 int rc = NS_LDAP_SUCCESS, len = 0;
3844 void **param = NULL;
3845 char *str = NULL;
3847 *allocated = FALSE;
3848 *new_dn = NULL;
3850 if (dn == NULL)
3851 return (NS_LDAP_INVALID_PARAM);
3853 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3854 (void ***)&param, errp);
3856 if (rc != NS_LDAP_SUCCESS) {
3857 if (param)
3858 (void) __ns_ldap_freeParam(&param);
3859 return (rc);
3862 len = strlen(dn);
3863 str = ((char **)param)[0];
3864 len = len + strlen(str) +1;
3865 *new_dn = (char *)malloc(len);
3866 if (*new_dn == NULL) {
3867 (void) __ns_ldap_freeParam(&param);
3868 return (NS_LDAP_MEMORY);
3870 *allocated = TRUE;
3872 (void) strcpy(*new_dn, dn);
3873 (void) strcat(*new_dn, str);
3875 (void) __ns_ldap_freeParam(&param);
3876 return (NS_LDAP_SUCCESS);
3880 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
3881 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
3882 * The output contains a count, a list of offsets, which show where the
3883 * corresponding copied attribute type and attribute value are located.
3884 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
3885 * the output is the ldap_strlist_t structure with: ldap_count = 6,
3886 * (buf + ldap_offsets[0]) -> "dn"
3887 * (buf + ldap_offsets[1]) -> "aaaa"
3888 * (buf + ldap_offsets[2]) -> "userPassword"
3889 * (buf + ldap_offsets[3]) -> "bbbb"
3890 * (buf + ldap_offsets[4]) -> "shadowlastchange"
3891 * (buf + ldap_offsets[5]) -> "cccc"
3892 * and all the string data shown above copied into the buffer after
3893 * the offset array. The total length of the data will be the return
3894 * value, or -1 if error.
3896 static int
3897 attr2list(const char *dn, ns_ldap_attr_t **attr,
3898 char *buf, int bufsize)
3900 int c = 0;
3901 char *ap;
3902 int ao;
3903 ldap_strlist_t *al = (ldap_strlist_t *)buf;
3904 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
3905 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
3907 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
3908 if ((strlen(dn) + 2 + 1) >= bufsize)
3909 return (-1);
3911 /* count number of attributes */
3912 while (*aptr++)
3913 c++;
3914 al->ldap_count = 2 + c * 2;
3915 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
3916 al->ldap_count;
3917 if (ao > bufsize)
3918 return (-1);
3919 al->ldap_offsets[0] = ao;
3920 ap = buf + ao;
3921 ao += 3;
3923 /* copy entry DN */
3924 if (ao > bufsize)
3925 return (-1);
3926 (void) strlcpy(ap, "dn", bufsize);
3927 ap += 3;
3929 al->ldap_offsets[1] = ao;
3930 ao += strlen(dn) + 1;
3931 if (ao > bufsize)
3932 return (-1);
3933 (void) strlcpy(ap, dn, bufsize);
3934 ap = buf + ao;
3936 aptr = attr;
3937 for (c = 2; c < al->ldap_count; c++, aptr++) {
3938 a = *aptr;
3939 if (a->attrname == NULL || a->attrvalue == NULL ||
3940 a->value_count != 1 || a->attrvalue[0] == NULL)
3941 return (-1);
3942 al->ldap_offsets[c] = ao;
3943 ao += strlen(a->attrname) + 1;
3944 if (ao > bufsize)
3945 return (-1);
3946 (void) strlcpy(ap, a->attrname, bufsize);
3947 ap = buf + ao;
3949 c++;
3950 al->ldap_offsets[c] = ao;
3951 ao += strlen(a->attrvalue[0]) + 1;
3952 (void) strlcpy(ap, a->attrvalue[0], bufsize);
3953 ap = buf + ao;
3956 return (ao);
3960 * Send a modify request to the ldap_cachemgr daemon
3961 * which will use the admin credential to perform the
3962 * operation.
3965 static int
3966 send_to_cachemgr(
3967 const char *dn,
3968 ns_ldap_attr_t **attr,
3969 ns_ldap_error_t **errorp)
3971 union {
3972 ldap_data_t s_d;
3973 char s_b[DOORBUFFERSIZE];
3974 } space;
3976 ldap_data_t *sptr;
3977 int ndata;
3978 int adata;
3979 int len;
3980 int rc;
3981 char errstr[MAXERROR];
3982 ldap_admin_mod_result_t *admin_result;
3984 *errorp = NULL;
3985 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
3986 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
3987 sizeof (space) - offsetof(ldap_return_t, ldap_u));
3988 if (len <= 0)
3989 return (NS_LDAP_INVALID_PARAM);
3991 adata = sizeof (ldap_call_t) + len;
3992 ndata = sizeof (space);
3993 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
3994 sptr = &space.s_d;
3996 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
3997 case NS_CACHE_SUCCESS:
3998 break;
3999 case NS_CACHE_NOTFOUND:
4000 (void) snprintf(errstr, sizeof (errstr),
4001 gettext("Door call ADMINMODIFY to "
4002 "ldap_cachemgr failed - error: %d"),
4003 space.s_d.ldap_ret.ldap_errno);
4004 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
4005 strdup(errstr), 0);
4006 return (NS_LDAP_OP_FAILED);
4007 default:
4008 return (NS_LDAP_OP_FAILED);
4011 admin_result = &sptr->ldap_ret.ldap_u.admin_result;
4012 if (admin_result->ns_err == NS_LDAP_SUCCESS)
4013 rc = NS_LDAP_SUCCESS;
4014 else {
4015 rc = admin_result->ns_err;
4016 if (admin_result->msg_size == 0)
4017 *errorp = __s_api_make_error(admin_result->status,
4018 NULL);
4019 else
4020 *errorp = __s_api_make_error(admin_result->status,
4021 admin_result->msg);
4024 /* clean up the door call */
4025 if (sptr != &space.s_d) {
4026 (void) munmap((char *)sptr, ndata);
4029 return (rc);