Unleashed v1.4
[unleashed.git] / usr / src / lib / libsldap / common / ns_writes.c
blob6a268c029fc0279514bc3570c22ae3fc0519ba1d
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 <priv.h>
62 #include <sys/param.h>
64 static int send_to_cachemgr(const char *,
65 ns_ldap_attr_t **, ns_ldap_error_t **);
67 static int escape_str(char *, char *);
70 * If the rdn is a mapped attr:
71 * return NS_LDAP_SUCCESS and a new_dn.
72 * If no mapped attr is found in the rdn:
73 * return NS_LDAP_SUCCESS and *new_dn == NULL
74 * For example:
75 * service = abc
76 * dn = cn=foo,dc=bar,dc=com
77 * attributeMapping: abc:cn=sn
78 * Then:
79 * new_dn = sn=foo,dc=bar,dc=com
82 static int
83 replace_mapped_attr_in_dn(
84 const char *service, const char *dn, char **new_dn)
86 char **mappedattr;
87 char **dnArray = NULL;
88 char *rservice;
89 char *cur = NULL;
90 int len = 0, orig_len = 0, mapped_len = 0;
91 int dn_len = 0;
93 *new_dn = NULL;
96 * separate dn into individual componets
97 * e.g.
98 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
100 dnArray = ldap_explode_dn(dn, 0);
101 if (!dnArray || !*dnArray)
102 return (NS_LDAP_INVALID_PARAM);
104 cur = strchr(dnArray[0], '=');
105 if (!cur) {
106 __s_api_free2dArray(dnArray);
107 return (NS_LDAP_INVALID_PARAM);
109 *cur = '\0';
111 /* we only check schema mapping for automount, not for auto_* */
112 if (strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
113 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
114 rservice = "automount";
115 else
116 rservice = (char *)service;
118 mappedattr = __ns_ldap_getMappedAttributes(rservice, dnArray[0]);
119 if (!mappedattr || !mappedattr[0]) {
120 __s_api_free2dArray(dnArray);
121 if (mappedattr)
122 __s_api_free2dArray(mappedattr);
123 return (NS_LDAP_SUCCESS);
125 orig_len = strlen(dnArray[0]);
128 * The new length is *dn length + (difference between
129 * orig attr and mapped attr) + 1 ;
130 * e.g.
131 * automountKey=aa,automountMapName=auto_home,dc=foo,dc=com
132 * ==>
133 * cn=aa,automountMapName=auto_home,dc=foo,dc=com
135 mapped_len = strlen(mappedattr[0]);
136 dn_len = strlen(dn);
137 len = dn_len - orig_len + mapped_len + 1;
138 *new_dn = (char *)calloc(1, len);
139 if (*new_dn == NULL) {
140 __s_api_free2dArray(dnArray);
141 __s_api_free2dArray(mappedattr);
142 return (NS_LDAP_MEMORY);
145 (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
146 __s_api_free2dArray(dnArray);
147 __s_api_free2dArray(mappedattr);
149 return (NS_LDAP_SUCCESS);
154 * The following function is only used by the
155 * "gecos" 1 to N attribute mapping code. It expects
156 * and handle only one data/length pair.
158 static int
159 init_bval_mod(
160 LDAPMod *mod,
161 int mop,
162 char *mtype,
163 char *mvptr,
164 int mvlen)
167 struct berval **bmodval;
169 /* dup attribute name */
170 mod->mod_type = strdup(mtype);
171 if (mod->mod_type == NULL)
172 return (-1);
175 * assume single value,
176 * since only one value/length pair passed in
178 bmodval = (struct berval **)calloc(2, sizeof (struct berval *));
179 if (bmodval == NULL) {
180 free(mod->mod_type);
181 mod->mod_type = NULL;
182 return (-1);
184 bmodval[0] = (struct berval *)calloc(1, sizeof (struct berval));
185 if (bmodval[0] == NULL) {
186 free(mod->mod_type);
187 mod->mod_type = NULL;
188 free(bmodval);
189 return (-1);
192 /* set pointer to data */
193 bmodval[0]->bv_val = mvptr;
195 /* set length */
196 bmodval[0]->bv_len = mvlen;
199 * turn on the BVALUE bit to indicate
200 * that the length of data is supplied
202 mod->mod_op = mop | LDAP_MOD_BVALUES;
204 mod->mod_bvalues = bmodval;
206 return (0);
209 static void
210 freeModList(LDAPMod **mods)
212 int i, j;
213 int name_is_oc;
215 if (mods == NULL)
216 return;
218 for (i = 0; mods[i]; i++) {
220 /* free attribute name */
221 name_is_oc = FALSE;
222 if (mods[i]->mod_type) {
223 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0)
224 name_is_oc = TRUE;
225 free(mods[i]->mod_type);
228 if (mods[i]->mod_bvalues == NULL)
229 continue;
231 * LDAP_MOD_BVALUES is only set by
232 * the "gecos" 1 to N attribute mapping
233 * code, and the attribute is single valued.
235 if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
236 free(mods[i]->mod_bvalues[0]);
237 } else {
238 if (name_is_oc) {
240 * only values for the "objectclass"
241 * were dupped using strdup.
242 * other attribute values were
243 * not dupped, but via pointer
244 * assignment. So here the
245 * values for "objectclass"
246 * is freed one by one,
247 * but the values for other
248 * attributes need not be freed.
250 for (j = 0; mods[i]->mod_values[j]; j++)
251 free(mods[i]->mod_values[j]);
255 free(mods[i]->mod_bvalues);
258 /* modlist */
259 free((char *)(mods[0]));
260 free(mods);
263 static LDAPMod **
264 __s_api_makeModListCount(
265 const char *service,
266 const ns_ldap_attr_t * const *attr,
267 const int mod_op,
268 const int count,
269 const int flags)
271 LDAPMod **mods, *modlist;
272 char **modval;
273 char **mapping;
274 int i;
275 int j;
276 int k, rc, vlen;
277 char *c, *comma1 = NULL, *comma2 = NULL;
278 int schema_mapping_existed = FALSE;
279 int auto_service = FALSE;
283 * add 2 for "gecos" 1 to up to 3 attribute mapping
285 mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
286 if (mods == NULL) {
287 return (NULL);
290 * add 2 for "gecos" 1 to up to 3 attribute mapping
292 modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
293 if (modlist == NULL) {
294 free(mods);
295 return (NULL);
298 if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
299 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
300 auto_service = TRUE;
303 * see if schema mapping existed for the given service
305 mapping = __ns_ldap_getOrigAttribute(service,
306 NS_HASH_SCHEMA_MAPPING_EXISTED);
307 if (mapping) {
308 schema_mapping_existed = TRUE;
309 __s_api_free2dArray(mapping);
310 mapping = NULL;
313 for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
314 mods[i] = &modlist[i];
315 mods[i]->mod_op = mod_op;
317 * Perform attribute mapping if necessary.
319 if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) {
320 mapping = __ns_ldap_getMappedAttributes(service,
321 attr[k]->attrname);
322 } else
323 mapping = NULL;
325 if (mapping == NULL && auto_service &&
326 (flags & NS_LDAP_NOMAP) == 0) {
328 * if service == auto_xxx and
329 * no mapped attribute is found
330 * and NS_LDAP_NOMAP is not set
331 * then try automount's mapped attribute
333 mapping = __ns_ldap_getMappedAttributes("automount",
334 attr[k]->attrname);
337 if (mapping == NULL) {
338 mods[i]->mod_type = strdup(attr[k]->attrname);
339 if (mods[i]->mod_type == NULL)
340 goto free_memory;
341 } else {
343 * 1 to N attribute mapping is only done for "gecos",
344 * and only 1 to 3 mapping.
345 * nine cases here:
347 * A. attrMap=passwd:gecos=a
348 * 1. gecos="xx,yy,zz" -> a="xx,yy,zz"
349 * 2. gecos="xx,yy" -> a="xx,yy"
350 * 3. gecos="xx" -> a="xx"
352 * B. attrMap=passwd:gecos=a b
353 * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
354 * 5. gecos="xx,yy" -> a="xx" b="yy"
355 * 6. gecos="xx" -> a="xx"
357 * C. attrMap=passwd:gecos=a b c
358 * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
359 * 8. gecos="xx,yy" -> a="xx" b="yy"
360 * 9. gecos="xx" -> a="xx"
362 * This can be grouped as:
364 * c1 cases: 1,2,3,6,9
365 * if ((attrMap=passwd:gecos=a) ||
366 * (no "," in gecos value))
367 * same as other no-mapping attributes,
368 * no special processing needed
369 * else
371 * c2 cases: 4,5,8
372 * if ((attrMap=passwd:gecos=a b) ||
373 * (only one "," in gecos value))
374 * a=xx b=yy[,...]
375 * else
377 * c3 case: 7
378 * a=xx b=yy c=...
380 * notes: in case c2 and c3, ... could still contain ","
382 if (strcasecmp(service, "passwd") == 0 &&
383 strcasecmp(attr[k]->attrname, "gecos") == 0 &&
384 mapping[1] && attr[k]->attrvalue[0] &&
385 (comma1 = strchr(attr[k]->attrvalue[0],
386 COMMATOK)) != NULL) {
388 /* is there a second comma? */
389 if (*(comma1 + 1) != '\0')
390 comma2 = strchr(comma1 + 1, COMMATOK);
393 * Process case c2 or c3.
394 * case c2: mapped to two attributes or just
395 * one comma
397 if (mapping[2] == NULL || comma2 == NULL) {
398 /* case c2 */
401 * int mod structure for the first attribute
403 vlen = comma1 - attr[k]->attrvalue[0];
404 c = attr[k]->attrvalue[0];
406 if (vlen > 0 && c) {
407 rc = init_bval_mod(mods[i], mod_op,
408 mapping[0], c, vlen);
409 if (rc != 0)
410 goto free_memory;
411 } else {
412 /* don't leave a hole in mods array */
413 mods[i] = NULL;
414 i--;
419 * init mod structure for the 2nd attribute
421 if (*(comma1 + 1) == '\0') {
422 __s_api_free2dArray(mapping);
423 mapping = NULL;
424 continue;
427 i++;
428 mods[i] = &modlist[i];
431 * get pointer to data.
432 * Skip leading spaces.
434 for (c = comma1 + 1; *c == SPACETOK; c++) {
435 /* empty */
438 /* get data length */
439 vlen = strlen(attr[k]->attrvalue[0]) -
440 (c - attr[k]->attrvalue[0]);
442 if (vlen > 0 && c) {
443 rc = init_bval_mod(mods[i], mod_op,
444 mapping[1], c, vlen);
445 if (rc != 0)
446 goto free_memory;
447 } else {
448 /* don't leave a hole in mods array */
449 mods[i] = NULL;
450 i--;
453 /* done with the mapping array */
454 __s_api_free2dArray(mapping);
455 mapping = NULL;
457 continue;
458 } else {
459 /* case c3 */
462 * int mod structure for the first attribute
464 vlen = comma1 - attr[k]->attrvalue[0];
465 c = attr[k]->attrvalue[0];
467 if (vlen > 0 && c) {
468 rc = init_bval_mod(mods[i], mod_op,
469 mapping[0], c, vlen);
470 if (rc != 0)
471 goto free_memory;
472 } else {
473 /* don't leave a hole in mods array */
474 mods[i] = NULL;
475 i--;
479 * init mod structure for the 2nd attribute
481 i++;
482 mods[i] = &modlist[i];
485 * get pointer to data.
486 * Skip leading spaces.
488 for (c = comma1 + 1; *c == SPACETOK; c++) {
489 /* empty */
492 /* get data length */
493 vlen = comma2 - c;
495 if (vlen > 0 && c) {
496 rc = init_bval_mod(mods[i], mod_op,
497 mapping[1], c, vlen);
498 if (rc != 0)
499 goto free_memory;
500 } else {
501 /* don't leave a hole in mods array */
502 mods[i] = NULL;
503 i--;
507 * init mod structure for the 3rd attribute
509 if (*(comma2 + 1) == '\0') {
510 __s_api_free2dArray(mapping);
511 mapping = NULL;
512 continue;
515 i++;
516 mods[i] = &modlist[i];
518 * get pointer to data.
519 * Skip leading spaces.
521 for (c = comma2 + 1; *c == SPACETOK; c++) {
522 /* empty */
525 /* get data length */
526 vlen = strlen(attr[k]->attrvalue[0]) -
527 (c - attr[k]->attrvalue[0]);
529 if (vlen > 0 && c) {
530 rc = init_bval_mod(mods[i], mod_op,
531 mapping[2], c, vlen);
532 if (rc != 0)
533 goto free_memory;
534 } else {
535 /* don't leave a hole in mods array */
536 mods[i] = NULL;
537 i--;
540 /* done with the mapping array */
541 __s_api_free2dArray(mapping);
542 mapping = NULL;
544 continue;
548 /* case c1 */
549 mods[i]->mod_type = strdup(mapping[0]);
550 if (mods[i]->mod_type == NULL) {
551 goto free_memory;
553 __s_api_free2dArray(mapping);
554 mapping = NULL;
557 modval = (char **)calloc(attr[k]->value_count+1,
558 sizeof (char *));
559 if (modval == NULL)
560 goto free_memory;
562 * Perform objectclass mapping.
563 * Note that the values for the "objectclass" attribute
564 * will be dupped using strdup. Values for other
565 * attributes will be referenced via pointer
566 * assignments.
568 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
569 for (j = 0; j < attr[k]->value_count; j++) {
570 if (schema_mapping_existed &&
571 (flags & NS_LDAP_NOMAP) == 0)
572 mapping =
573 __ns_ldap_getMappedObjectClass(
574 service, attr[k]->attrvalue[j]);
575 else
576 mapping = NULL;
578 if (mapping == NULL && auto_service &&
579 (flags & NS_LDAP_NOMAP) == 0)
581 * if service == auto_xxx and
582 * no mapped objectclass is found
583 * then try automount
585 mapping =
586 __ns_ldap_getMappedObjectClass(
587 "automount", attr[k]->attrvalue[j]);
589 if (mapping && mapping[0]) {
590 /* assume single mapping */
591 modval[j] = strdup(mapping[0]);
592 } else {
593 modval[j] = strdup(attr[k]->
594 attrvalue[j]);
596 if (modval[j] == NULL)
597 goto free_memory;
599 } else {
600 for (j = 0; j < attr[k]->value_count; j++) {
601 /* ASSIGN NOT COPY */
602 modval[j] = attr[k]->attrvalue[j];
605 mods[i]->mod_values = modval;
608 return (mods);
610 free_memory:
611 freeModList(mods);
612 if (mapping)
613 __s_api_free2dArray(mapping);
615 return (NULL);
619 static LDAPMod **
620 __s_api_makeModList(
621 const char *service,
622 const ns_ldap_attr_t * const *attr,
623 const int mod_op,
624 const int flags)
626 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
627 int count = 0;
629 if (aptr == NULL)
630 return (NULL);
632 /* count number of attributes */
633 while (*aptr++)
634 count++;
636 return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
639 static void
640 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
642 if (*entry != NULL) {
643 __ns_ldap_freeEntry(*entry);
644 *entry = NULL;
646 if (*rdn != NULL) {
647 free(*rdn);
648 *rdn = NULL;
653 * This state machine performs one or more LDAP add/delete/modify
654 * operations to configured LDAP servers.
656 static int
657 write_state_machine(
658 int ldap_op,
659 char *dn,
660 LDAPMod **mods,
661 const ns_cred_t *cred,
662 const int flags,
663 ns_ldap_error_t ** errorp)
665 ConnectionID connectionId = -1;
666 Connection *conp = NULL;
667 LDAPMessage *res;
668 char *target_dn = NULL;
669 char errstr[MAXERROR];
670 int rc = NS_LDAP_SUCCESS;
671 int return_rc = NS_LDAP_SUCCESS;
672 int followRef = FALSE;
673 int target_dn_allocated = FALSE;
674 int len;
675 int msgid;
676 int Errno;
677 boolean_t from_get_lderrno = B_FALSE;
678 int always = 1;
679 char *err, *errmsg = NULL;
680 /* referrals returned by the LDAP operation */
681 char **referrals = NULL;
683 * list of referrals used by the state machine, built from
684 * the referrals variable above
686 ns_referral_info_t *ref_list = NULL;
687 /* current referral */
688 ns_referral_info_t *current_ref = NULL;
689 ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
690 int do_not_fail_if_new_pwd_reqd = 0;
691 ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD;
692 int passwd_mgmt = 0;
693 int i = 0;
694 int ldap_error;
695 int nopasswd_acct_mgmt = 0;
696 ns_conn_user_t *conn_user = NULL;
698 while (always) {
699 switch (state) {
700 case W_EXIT:
701 /* return the MT connection and free the conn user */
702 if (conn_user != NULL) {
703 if (conn_user->use_mt_conn == B_TRUE) {
704 if (conn_user->ns_error != NULL) {
705 *errorp = conn_user->ns_error;
706 conn_user->ns_error = NULL;
707 return_rc = conn_user->ns_rc;
709 if (conn_user->conn_mt != NULL)
710 __s_api_conn_mt_return(
711 conn_user);
713 __s_api_conn_user_free(conn_user);
716 if (connectionId > -1)
717 DropConnection(connectionId, NS_LDAP_NEW_CONN);
718 if (ref_list)
719 __s_api_deleteRefInfo(ref_list);
720 if (target_dn && target_dn_allocated)
721 free(target_dn);
722 return (return_rc);
723 case W_INIT:
724 /* see if need to follow referrals */
725 rc = __s_api_toFollowReferrals(flags,
726 &followRef, errorp);
727 if (rc != NS_LDAP_SUCCESS) {
728 return_rc = rc;
729 new_state = W_ERROR;
730 break;
732 len = strlen(dn);
733 if (dn[len-1] == COMMATOK)
734 rc = __s_api_append_default_basedn(
735 dn, &target_dn, &target_dn_allocated,
736 errorp);
737 else
738 target_dn = dn;
739 if (rc != NS_LDAP_SUCCESS) {
740 return_rc = rc;
741 new_state = W_ERROR;
743 else
744 new_state = GET_CONNECTION;
745 break;
746 case GET_CONNECTION:
747 /* identify self as a write user */
748 conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE,
749 NULL, B_FALSE);
750 rc = __s_api_getConnection(NULL,
751 flags, cred, &connectionId, &conp, errorp,
752 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
753 conn_user);
756 * If password control attached
757 * in *errorp,
758 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
759 * free the error structure (we do not need
760 * the password management info).
761 * Reset rc to NS_LDAP_SUCCESS.
763 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
764 (void) __ns_ldap_freeError(errorp);
765 *errorp = NULL;
766 rc = NS_LDAP_SUCCESS;
769 if (rc != NS_LDAP_SUCCESS) {
770 return_rc = rc;
771 new_state = W_ERROR;
772 break;
774 if (followRef)
775 new_state = SELECT_OPERATION_ASYNC;
776 else
777 new_state = SELECT_OPERATION_SYNC;
778 break;
779 case SELECT_OPERATION_SYNC:
780 if (ldap_op == LDAP_REQ_ADD)
781 new_state = DO_ADD_SYNC;
782 else if (ldap_op == LDAP_REQ_DELETE)
783 new_state = DO_DELETE_SYNC;
784 else if (ldap_op == LDAP_REQ_MODIFY)
785 new_state = DO_MODIFY_SYNC;
786 break;
787 case SELECT_OPERATION_ASYNC:
788 if (ldap_op == LDAP_REQ_ADD)
789 new_state = DO_ADD_ASYNC;
790 else if (ldap_op == LDAP_REQ_DELETE)
791 new_state = DO_DELETE_ASYNC;
792 else if (ldap_op == LDAP_REQ_MODIFY)
793 new_state = DO_MODIFY_ASYNC;
794 break;
795 case DO_ADD_SYNC:
796 rc = ldap_add_ext_s(conp->ld, target_dn,
797 mods, NULL, NULL);
798 new_state = GET_RESULT_SYNC;
799 break;
800 case DO_DELETE_SYNC:
801 rc = ldap_delete_ext_s(conp->ld, target_dn,
802 NULL, NULL);
803 new_state = GET_RESULT_SYNC;
804 break;
805 case DO_MODIFY_SYNC:
806 rc = ldap_modify_ext_s(conp->ld, target_dn,
807 mods, NULL, NULL);
808 new_state = GET_RESULT_SYNC;
809 break;
810 case DO_ADD_ASYNC:
811 rc = ldap_add_ext(conp->ld, target_dn,
812 mods, NULL, NULL, &msgid);
813 new_state = GET_RESULT_ASYNC;
814 break;
815 case DO_DELETE_ASYNC:
816 rc = ldap_delete_ext(conp->ld, target_dn,
817 NULL, NULL, &msgid);
818 new_state = GET_RESULT_ASYNC;
819 break;
820 case DO_MODIFY_ASYNC:
821 rc = ldap_modify_ext(conp->ld, target_dn,
822 mods, NULL, NULL, &msgid);
823 new_state = GET_RESULT_ASYNC;
824 break;
825 case GET_RESULT_SYNC:
826 if (rc != LDAP_SUCCESS) {
827 Errno = rc;
828 (void) ldap_get_lderrno(conp->ld,
829 NULL, &errmsg);
832 * No need to deal with the error message if
833 * it's an empty string.
835 if (errmsg != NULL && *errmsg == '\0')
836 errmsg = NULL;
838 if (errmsg != NULL) {
840 * ldap_get_lderrno does not expect
841 * errmsg to be freed after use, while
842 * ldap_parse_result below does, so set
843 * a flag to indicate source.
845 from_get_lderrno = B_TRUE;
848 new_state = W_LDAP_ERROR;
849 } else {
850 return_rc = NS_LDAP_SUCCESS;
851 new_state = W_EXIT;
853 break;
854 case GET_RESULT_ASYNC:
855 rc = ldap_result(conp->ld, msgid, 1,
856 NULL, &res);
857 /* if no server response, set Errno */
858 if (rc == -1) {
859 (void) ldap_get_option(conp->ld,
860 LDAP_OPT_ERROR_NUMBER, &Errno);
861 new_state = W_LDAP_ERROR;
862 break;
864 if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY ||
865 rc == LDAP_RES_DELETE) {
866 new_state = PARSE_RESULT;
867 break;
868 } else {
869 return_rc = rc;
870 new_state = W_ERROR;
872 break;
873 case PARSE_RESULT:
875 * need Errno, referrals, error msg,
876 * and the last "1" is to free
877 * the result (res)
879 rc = ldap_parse_result(conp->ld, res, &Errno,
880 NULL, &errmsg, &referrals, NULL, 1);
882 * free errmsg if it is an empty string
884 if (errmsg && *errmsg == '\0') {
885 ldap_memfree(errmsg);
886 errmsg = NULL;
889 * If we received referral data, process
890 * it if:
891 * - we are configured to follow referrals
892 * - and not already in referral mode (to keep
893 * consistency with search_state_machine()
894 * which follows 1 level of referrals only;
895 * see proc_result_referrals() and
896 * proc_search_references().
898 if (Errno == LDAP_REFERRAL && followRef && !ref_list) {
899 for (i = 0; referrals[i] != NULL; i++) {
900 /* add to referral list */
901 rc = __s_api_addRefInfo(&ref_list,
902 referrals[i], NULL, NULL, NULL,
903 conp->ld);
904 if (rc != NS_LDAP_SUCCESS) {
905 __s_api_deleteRefInfo(ref_list);
906 ref_list = NULL;
907 break;
910 ldap_value_free(referrals);
911 if (ref_list == NULL) {
912 if (rc != NS_LDAP_MEMORY)
913 rc = NS_LDAP_INTERNAL;
914 return_rc = rc;
915 new_state = W_ERROR;
916 } else {
917 new_state = GET_REFERRAL_CONNECTION;
918 current_ref = ref_list;
920 if (errmsg) {
921 ldap_memfree(errmsg);
922 errmsg = NULL;
924 break;
926 if (Errno != LDAP_SUCCESS) {
927 new_state = W_LDAP_ERROR;
928 } else {
929 return_rc = NS_LDAP_SUCCESS;
930 new_state = W_EXIT;
932 break;
933 case GET_REFERRAL_CONNECTION:
935 * since we are starting over,
936 * discard the old error info
938 return_rc = NS_LDAP_SUCCESS;
939 if (*errorp)
940 (void) __ns_ldap_freeError(errorp);
941 if (connectionId > -1)
942 DropConnection(connectionId, NS_LDAP_NEW_CONN);
944 /* set it up to use a referral connection */
945 if (conn_user != NULL) {
947 * If an MT connection is being used,
948 * return it to the pool.
950 if (conn_user->conn_mt != NULL)
951 __s_api_conn_mt_return(conn_user);
953 conn_user->referral = B_TRUE;
955 rc = __s_api_getConnection(current_ref->refHost,
956 0, cred, &connectionId, &conp, errorp,
957 do_not_fail_if_new_pwd_reqd,
958 nopasswd_acct_mgmt, conn_user);
961 * If password control attached
962 * in errorp,
963 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
964 * free the error structure (we do not need
965 * the password management info).
966 * Reset rc to NS_LDAP_SUCCESS.
968 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
969 (void) __ns_ldap_freeError(errorp);
970 *errorp = NULL;
971 rc = NS_LDAP_SUCCESS;
974 if (rc != NS_LDAP_SUCCESS) {
975 return_rc = rc;
977 * If current referral is not
978 * available for some reason,
979 * try next referral in the list.
980 * Get LDAP error code from errorp.
982 if (*errorp != NULL) {
983 ns_write_state_t get_ref =
984 GET_REFERRAL_CONNECTION;
986 ldap_error = (*errorp)->status;
987 if (ldap_error == LDAP_BUSY ||
988 ldap_error == LDAP_UNAVAILABLE ||
989 ldap_error ==
990 LDAP_UNWILLING_TO_PERFORM ||
991 ldap_error == LDAP_CONNECT_ERROR ||
992 ldap_error == LDAP_SERVER_DOWN) {
993 current_ref = current_ref->next;
994 if (current_ref == NULL) {
995 /* no more referral to follow */
996 new_state = W_ERROR;
997 } else
998 new_state = get_ref;
1000 * free errorp before going to
1001 * next referral
1003 (void) __ns_ldap_freeError(
1004 errorp);
1005 *errorp = NULL;
1006 break;
1009 * free errorp before going to W_ERROR
1011 (void) __ns_ldap_freeError(errorp);
1012 *errorp = NULL;
1014 /* else, exit */
1015 __s_api_deleteRefInfo(ref_list);
1016 ref_list = NULL;
1017 new_state = W_ERROR;
1018 if (conn_user != NULL)
1019 conn_user->referral = B_FALSE;
1020 break;
1022 /* target DN may changed due to referrals */
1023 if (current_ref->refDN) {
1024 if (target_dn && target_dn_allocated) {
1025 free(target_dn);
1026 target_dn = NULL;
1027 target_dn_allocated = FALSE;
1029 target_dn = current_ref->refDN;
1031 new_state = SELECT_OPERATION_SYNC;
1032 break;
1033 case W_LDAP_ERROR:
1035 * map error code and error message
1036 * to password status if necessary.
1037 * This is to see if password updates
1038 * failed due to password policy or
1039 * password syntax checking.
1041 if (errmsg) {
1043 * check if server supports
1044 * password management
1046 passwd_mgmt =
1047 __s_api_contain_passwd_control_oid(
1048 conp->controls);
1049 if (passwd_mgmt)
1050 pwd_status =
1051 __s_api_set_passwd_status(
1052 Errno, errmsg);
1054 * free only if not returned by ldap_get_lderrno
1056 if (!from_get_lderrno)
1057 ldap_memfree(errmsg);
1058 errmsg = NULL;
1059 from_get_lderrno = B_FALSE;
1062 (void) snprintf(errstr, sizeof (errstr),
1063 "%s", ldap_err2string(Errno));
1064 err = strdup(errstr);
1065 if (pwd_status != NS_PASSWD_GOOD) {
1066 MKERROR_PWD_MGMT(*errorp, Errno, err,
1067 pwd_status, 0, 0);
1068 } else {
1069 MKERROR(LOG_INFO, *errorp, Errno, err, 0);
1071 if (conn_user != NULL &&
1072 (Errno == LDAP_SERVER_DOWN ||
1073 Errno == LDAP_CONNECT_ERROR)) {
1074 __s_api_conn_mt_close(conn_user, Errno, errorp);
1076 return_rc = NS_LDAP_INTERNAL;
1077 new_state = W_EXIT;
1078 break;
1079 case W_ERROR:
1080 default:
1081 (void) sprintf(errstr,
1082 gettext("Internal write State machine exit"
1083 " (state = %d, rc = %d)."),
1084 err_state, return_rc);
1085 err = strdup(errstr);
1086 MKERROR(LOG_WARNING, *errorp, return_rc, err, 0);
1087 new_state = W_EXIT;
1088 break;
1091 if (new_state == W_ERROR)
1092 err_state = state;
1094 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
1095 __s_api_conn_mt_close(conn_user, 0, NULL);
1096 new_state = W_EXIT;
1099 state = new_state;
1103 * should never be here, the next line is to eliminating
1104 * lint message
1106 return (NS_LDAP_INTERNAL);
1110 /*ARGSUSED*/
1112 __ns_ldap_addAttr(
1113 const char *service,
1114 const char *dn,
1115 const ns_ldap_attr_t * const *attr,
1116 const ns_cred_t *cred,
1117 const int flags,
1118 ns_ldap_error_t ** errorp)
1120 LDAPMod **mods;
1121 int rc = 0;
1123 #ifdef DEBUG
1124 (void) fprintf(stderr, "__ns_ldap_addAttr START\n");
1125 #endif
1126 *errorp = NULL;
1128 /* Sanity check */
1129 if ((attr == NULL) || (*attr == NULL) ||
1130 (dn == NULL) || (cred == NULL))
1131 return (NS_LDAP_INVALID_PARAM);
1133 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1134 if (mods == NULL) {
1135 return (NS_LDAP_MEMORY);
1138 rc = write_state_machine(LDAP_REQ_MODIFY,
1139 (char *)dn, mods, cred, flags, errorp);
1140 freeModList(mods);
1142 return (rc);
1146 /*ARGSUSED*/
1148 __ns_ldap_delAttr(
1149 const char *service,
1150 const char *dn,
1151 const ns_ldap_attr_t * const *attr,
1152 const ns_cred_t *cred,
1153 const int flags,
1154 ns_ldap_error_t ** errorp)
1156 LDAPMod **mods;
1157 int rc = 0;
1159 #ifdef DEBUG
1160 (void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1161 #endif
1162 *errorp = NULL;
1164 /* Sanity check */
1165 if ((attr == NULL) || (*attr == NULL) ||
1166 (dn == NULL) || (cred == NULL))
1167 return (NS_LDAP_INVALID_PARAM);
1169 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1170 if (mods == NULL) {
1171 return (NS_LDAP_MEMORY);
1174 rc = write_state_machine(LDAP_REQ_MODIFY,
1175 (char *)dn, mods, cred, flags, errorp);
1177 freeModList(mods);
1178 return (rc);
1181 /* Retrieve the admin bind password from the configuration, if allowed. */
1182 static int
1183 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
1185 void **paramVal = NULL;
1186 int rc, ldaprc;
1187 char *modparamVal = NULL;
1190 * For GSSAPI/Kerberos, host credential is used, no need to get
1191 * admin bind password
1193 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
1194 return (NS_LDAP_SUCCESS);
1197 * Retrieve admin bind password.
1198 * The admin bind password is available
1199 * only in the ldap_cachemgr process as
1200 * they are not exposed outside of that
1201 * process.
1203 paramVal = NULL;
1204 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1205 &paramVal, errorp)) != NS_LDAP_SUCCESS)
1206 return (ldaprc);
1207 if (paramVal == NULL || *paramVal == NULL) {
1208 rc = NS_LDAP_CONFIG;
1209 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
1210 gettext("Admin bind password not configured"));
1211 if (*errorp == NULL)
1212 rc = NS_LDAP_MEMORY;
1213 return (rc);
1215 modparamVal = dvalue((char *)*paramVal);
1216 (void) memset(*paramVal, 0, strlen((char *)*paramVal));
1217 (void) __ns_ldap_freeParam(&paramVal);
1218 if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
1219 free(modparamVal);
1220 rc = NS_LDAP_CONFIG;
1221 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
1222 gettext("bind password not valid"));
1223 if (*errorp == NULL)
1224 rc = NS_LDAP_MEMORY;
1225 return (rc);
1228 cred->cred.unix_cred.passwd = modparamVal;
1229 return (NS_LDAP_SUCCESS);
1232 boolean_t
1233 __ns_ldap_is_shadow_update_enabled(void)
1235 int **enable_shadow = NULL;
1236 ns_ldap_error_t *errorp = NULL;
1238 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1239 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1240 if (errorp)
1241 (void) __ns_ldap_freeError(&errorp);
1242 return (B_FALSE);
1244 if ((enable_shadow != NULL && *enable_shadow != NULL) &&
1245 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
1246 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1247 return (B_TRUE);
1249 if (enable_shadow != NULL)
1250 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1251 return (B_FALSE);
1255 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
1256 * on the LDAP server. 'service' indicates the type of database entries
1257 * to modify. When the Native LDAP client is configured with 'shadow update
1258 * enabled', Shadowshadow(4) entries can only be modified by privileged users.
1259 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
1260 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
1261 * for performing the LDAP modify operation. ldap_cachemgr would call
1262 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
1263 * to identify itself, so that admin credential would be obtained and
1264 * the actual LDAP modify operation be done.
1266 /*ARGSUSED*/
1268 __ns_ldap_repAttr(
1269 const char *service,
1270 const char *dn,
1271 const ns_ldap_attr_t * const *attr,
1272 const ns_cred_t *cred,
1273 const int flags,
1274 ns_ldap_error_t ** errorp)
1276 LDAPMod **mods;
1277 int rc = 0;
1278 boolean_t priv;
1279 boolean_t shadow_update_enabled = B_FALSE;
1281 #ifdef DEBUG
1282 (void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1283 #endif
1284 *errorp = NULL;
1286 /* Sanity check */
1287 if (attr == NULL || *attr == NULL || dn == NULL)
1288 return (NS_LDAP_INVALID_PARAM);
1290 /* Privileged shadow modify? */
1291 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
1292 strcmp(service, "shadow") == 0) {
1294 /* Shadow update enabled ? If not, error out */
1295 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
1296 if (!shadow_update_enabled) {
1297 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
1298 gettext("Shadow Update is not enabled"));
1299 return (NS_LDAP_CONFIG);
1302 /* privileged shadow modify requires euid 0 or all zone privs */
1303 priv = (geteuid() == 0);
1304 if (!priv) {
1305 priv_set_t *ps = priv_allocset(); /* caller */
1306 priv_set_t *zs; /* zone */
1308 (void) getppriv(PRIV_EFFECTIVE, ps);
1309 zs = priv_str_to_set("zone", ",", NULL);
1310 priv = priv_isequalset(ps, zs);
1311 priv_freeset(ps);
1312 priv_freeset(zs);
1314 if (!priv)
1315 return (NS_LDAP_OP_FAILED);
1317 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
1318 return (rc);
1321 if (cred == NULL)
1322 return (NS_LDAP_INVALID_PARAM);
1325 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
1326 * ldap_cachemgr. We need to get the admin cred to do work.
1327 * If the caller is not ldap_cachemgr, but use the service
1328 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
1329 * as the admin cred is not available to the caller.
1331 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
1332 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
1333 NS_LDAP_SUCCESS)
1334 return (rc);
1337 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1338 if (mods == NULL)
1339 return (NS_LDAP_MEMORY);
1341 rc = write_state_machine(LDAP_REQ_MODIFY,
1342 (char *)dn, mods, cred, flags, errorp);
1344 freeModList(mods);
1345 return (rc);
1348 /*ARGSUSED*/
1350 __ns_ldap_addEntry(
1351 const char *service,
1352 const char *dn,
1353 const ns_ldap_entry_t *entry,
1354 const ns_cred_t *cred,
1355 const int flags,
1356 ns_ldap_error_t ** errorp)
1358 char *new_dn = NULL;
1359 LDAPMod **mods = NULL;
1360 const ns_ldap_attr_t * const *attr;
1361 int nAttr = 0;
1362 int rc = 0;
1364 #ifdef DEBUG
1365 (void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1366 #endif
1368 if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1369 return (NS_LDAP_INVALID_PARAM);
1370 *errorp = NULL;
1372 /* Construct array of LDAPMod representing attributes of new entry. */
1374 nAttr = entry->attr_count;
1375 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1376 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1377 nAttr, flags);
1378 if (mods == NULL) {
1379 return (NS_LDAP_MEMORY);
1382 rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1383 if (rc != NS_LDAP_SUCCESS) {
1384 freeModList(mods);
1385 return (rc);
1388 rc = write_state_machine(LDAP_REQ_ADD,
1389 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1391 free(new_dn);
1392 freeModList(mods);
1393 return (rc);
1397 /*ARGSUSED*/
1399 __ns_ldap_delEntry(
1400 const char *service,
1401 const char *dn,
1402 const ns_cred_t *cred,
1403 const int flags,
1404 ns_ldap_error_t ** errorp)
1406 int rc;
1408 #ifdef DEBUG
1409 (void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1410 #endif
1411 if ((dn == NULL) || (cred == NULL))
1412 return (NS_LDAP_INVALID_PARAM);
1414 *errorp = NULL;
1416 rc = write_state_machine(LDAP_REQ_DELETE,
1417 (char *)dn, NULL, cred, flags, errorp);
1419 return (rc);
1423 * Add Typed Entry Helper routines
1427 * Add Typed Entry Conversion routines
1430 static int
1431 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1433 ns_ldap_attr_t *a;
1434 char *v;
1436 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1437 if (a == NULL)
1438 return (NS_LDAP_MEMORY);
1439 a->attrname = strdup(attrname);
1440 if (a->attrname == NULL)
1441 return (NS_LDAP_MEMORY);
1442 a->attrvalue = (char **)calloc(1, sizeof (char **));
1443 if (a->attrvalue == NULL)
1444 return (NS_LDAP_MEMORY);
1445 a->value_count = 1;
1446 a->attrvalue[0] = NULL;
1447 v = strdup(value);
1448 if (v == NULL)
1449 return (NS_LDAP_MEMORY);
1450 a->attrvalue[0] = v;
1451 e->attr_pair[e->attr_count] = a;
1452 e->attr_count++;
1453 return (NS_LDAP_SUCCESS);
1456 static int
1457 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1459 ns_ldap_attr_t *a;
1460 char *v;
1461 char **av;
1462 int i, j;
1464 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1465 if (a == NULL)
1466 return (NS_LDAP_MEMORY);
1467 a->attrname = strdup(attrname);
1468 if (a->attrname == NULL)
1469 return (NS_LDAP_MEMORY);
1471 for (i = 0, av = argv; *av != NULL; av++, i++)
1474 a->attrvalue = (char **)calloc(i, sizeof (char *));
1476 if (a->attrvalue == NULL)
1477 return (NS_LDAP_MEMORY);
1479 a->value_count = i;
1480 for (j = 0; j < i; j++) {
1481 v = strdup(argv[j]);
1482 if (v == NULL)
1483 return (NS_LDAP_MEMORY);
1484 a->attrvalue[j] = v;
1486 e->attr_pair[e->attr_count] = a;
1487 e->attr_count++;
1488 return (NS_LDAP_SUCCESS);
1491 static ns_ldap_entry_t *
1492 __s_mk_entry(char **objclass, int max_attr)
1494 ns_ldap_entry_t *e;
1495 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1496 if (e == NULL)
1497 return (NULL);
1498 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1499 e->attr_pair = (ns_ldap_attr_t **)
1500 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1501 if (e->attr_pair == NULL) {
1502 free(e);
1503 return (NULL);
1505 e->attr_count = 0;
1506 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1507 free(e->attr_pair);
1508 free(e);
1509 return (NULL);
1511 return (e);
1516 * Conversion: passwd
1517 * Input format: struct passwd
1518 * Exported objectclass: posixAccount
1520 static int
1521 __s_cvt_passwd(const void *data, char **rdn,
1522 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1524 ns_ldap_entry_t *e;
1525 int rc;
1526 char trdn[RDNSIZE];
1527 /* routine specific */
1528 struct passwd *ptr;
1529 int max_attr = 9;
1530 char ibuf[10];
1531 static char *oclist[] = {
1532 "posixAccount",
1533 "shadowAccount",
1534 "account",
1535 "top",
1536 NULL
1539 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1540 return (NS_LDAP_OP_FAILED);
1541 *entry = e = __s_mk_entry(oclist, max_attr);
1542 if (e == NULL)
1543 return (NS_LDAP_MEMORY);
1545 /* Convert the structure */
1546 ptr = (struct passwd *)data;
1548 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
1549 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
1550 __ns_ldap_freeEntry(e);
1551 *entry = NULL;
1552 return (NS_LDAP_INVALID_PARAM);
1555 /* Create an appropriate rdn */
1556 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1557 *rdn = strdup(trdn);
1558 if (*rdn == NULL) {
1559 __ns_ldap_freeEntry(e);
1560 *entry = NULL;
1561 return (NS_LDAP_MEMORY);
1564 /* Error check the data and add the attributes */
1565 rc = __s_add_attr(e, "uid", ptr->pw_name);
1566 if (rc != NS_LDAP_SUCCESS) {
1567 __s_cvt_freeEntryRdn(entry, rdn);
1568 return (rc);
1570 rc = __s_add_attr(e, "cn", ptr->pw_name);
1571 if (rc != NS_LDAP_SUCCESS) {
1572 __s_cvt_freeEntryRdn(entry, rdn);
1573 return (rc);
1576 if (ptr->pw_passwd != NULL &&
1577 ptr->pw_passwd[0] != '\0') {
1578 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1579 if (rc != NS_LDAP_SUCCESS) {
1580 __s_cvt_freeEntryRdn(entry, rdn);
1581 return (rc);
1585 (void) sprintf(ibuf, "%u", ptr->pw_uid);
1586 rc = __s_add_attr(e, "uidNumber", ibuf);
1587 if (rc != NS_LDAP_SUCCESS) {
1588 __s_cvt_freeEntryRdn(entry, rdn);
1589 return (rc);
1592 (void) sprintf(ibuf, "%u", ptr->pw_gid);
1593 rc = __s_add_attr(e, "gidNumber", ibuf);
1594 if (rc != NS_LDAP_SUCCESS) {
1595 __s_cvt_freeEntryRdn(entry, rdn);
1596 return (rc);
1598 if (ptr->pw_gecos != NULL &&
1599 ptr->pw_gecos[0] != '\0') {
1600 rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1601 if (rc != NS_LDAP_SUCCESS) {
1602 __s_cvt_freeEntryRdn(entry, rdn);
1603 return (rc);
1607 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1608 if (rc != NS_LDAP_SUCCESS) {
1609 __s_cvt_freeEntryRdn(entry, rdn);
1610 return (rc);
1612 if (ptr->pw_shell != NULL &&
1613 ptr->pw_shell[0] != '\0') {
1614 rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1615 if (rc != NS_LDAP_SUCCESS) {
1616 __s_cvt_freeEntryRdn(entry, rdn);
1617 return (rc);
1621 return (NS_LDAP_SUCCESS);
1625 * escape_str function escapes special characters in str and
1626 * copies to escstr string.
1628 * return 0 for successful
1629 * 1 for fail
1631 static int escape_str(char *escstr, char *str)
1633 int index = 0;
1635 while ((*str != '\0') && (index < (RDNSIZE - 1))) {
1636 if (*str == '+' || *str == ';' || *str == '>' ||
1637 *str == '<' || *str == ',' || *str == '"' ||
1638 *str == '\\' || *str == '=' ||
1639 (*str == '#' && index == 0)) {
1640 *escstr++ = '\\';
1641 *escstr++ = *str++;
1642 index += 2;
1643 } else {
1644 *escstr++ = *str++;
1645 index++;
1649 if (*str == '\0') {
1650 *escstr = '\0';
1651 return (0);
1652 } else {
1653 return (1);
1658 * Conversion: project
1659 * Input format: struct project
1660 * Exported objectclass: SolarisProject
1662 static int
1663 __s_cvt_project(const void *data, char **rdn,
1664 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1666 ns_ldap_entry_t *e;
1667 int rc;
1668 char trdn[RDNSIZE];
1670 /* routine specific */
1671 struct project *ptr;
1672 int max_attr = 9;
1673 char ibuf[11];
1674 static char *oclist[] = {
1675 "SolarisProject",
1676 "top",
1677 NULL
1680 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1681 return (NS_LDAP_OP_FAILED);
1683 *entry = e = __s_mk_entry(oclist, max_attr);
1684 if (e == NULL)
1685 return (NS_LDAP_MEMORY);
1687 /* Convert the structure */
1688 ptr = (struct project *)data;
1690 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
1691 __ns_ldap_freeEntry(e);
1692 *entry = NULL;
1693 return (NS_LDAP_INVALID_PARAM);
1696 /* Create an appropriate rdn */
1697 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
1698 *rdn = strdup(trdn);
1699 if (*rdn == NULL) {
1700 __ns_ldap_freeEntry(e);
1701 *entry = NULL;
1702 return (NS_LDAP_MEMORY);
1705 /* Error check the data and add the attributes */
1707 /* Project name */
1708 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
1709 if (rc != NS_LDAP_SUCCESS) {
1710 __s_cvt_freeEntryRdn(entry, rdn);
1711 return (rc);
1715 * Project ID:
1716 * ibuf is 11 chars big, which should be enough for string
1717 * representation of 32bit number + nul-car
1719 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
1720 __s_cvt_freeEntryRdn(entry, rdn);
1721 return (NS_LDAP_INVALID_PARAM);
1723 rc = __s_add_attr(e, "SolarisProjectID", ibuf);
1724 if (rc != NS_LDAP_SUCCESS) {
1725 __s_cvt_freeEntryRdn(entry, rdn);
1726 return (rc);
1729 /* Comment/Description */
1730 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
1731 rc = __s_add_attr(e, "description", ptr->pj_comment);
1732 if (rc != NS_LDAP_SUCCESS) {
1733 __s_cvt_freeEntryRdn(entry, rdn);
1734 return (rc);
1738 /* Attributes */
1739 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
1740 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
1741 if (rc != NS_LDAP_SUCCESS) {
1742 __s_cvt_freeEntryRdn(entry, rdn);
1743 return (rc);
1747 /* Users */
1748 if (ptr->pj_users != NULL) {
1749 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
1750 if (rc != NS_LDAP_SUCCESS) {
1751 __s_cvt_freeEntryRdn(entry, rdn);
1752 return (rc);
1756 /* Groups */
1757 if (ptr->pj_groups != NULL) {
1758 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
1759 if (rc != NS_LDAP_SUCCESS) {
1760 __s_cvt_freeEntryRdn(entry, rdn);
1761 return (rc);
1767 return (NS_LDAP_SUCCESS);
1770 * Conversion: shadow
1771 * Input format: struct shadow
1772 * Exported objectclass: shadowAccount
1774 static int
1775 __s_cvt_shadow(const void *data, char **rdn,
1776 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1778 ns_ldap_entry_t *e;
1779 int rc;
1780 char trdn[RDNSIZE];
1781 /* routine specific */
1782 struct spwd *ptr;
1783 int max_attr = 10;
1784 char ibuf[10];
1785 static char *oclist[] = {
1786 "posixAccount",
1787 "shadowAccount",
1788 "account",
1789 "top",
1790 NULL
1793 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1794 return (NS_LDAP_OP_FAILED);
1795 *entry = e = __s_mk_entry(oclist, max_attr);
1796 if (e == NULL)
1797 return (NS_LDAP_MEMORY);
1799 /* Convert the structure */
1800 ptr = (struct spwd *)data;
1802 if (ptr->sp_namp == NULL) {
1803 __ns_ldap_freeEntry(e);
1804 *entry = NULL;
1805 return (NS_LDAP_INVALID_PARAM);
1808 /* Create an appropriate rdn */
1809 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1810 *rdn = strdup(trdn);
1811 if (*rdn == NULL) {
1812 __ns_ldap_freeEntry(e);
1813 *entry = NULL;
1814 return (NS_LDAP_MEMORY);
1817 /* Error check the data and add the attributes */
1818 rc = __s_add_attr(e, "uid", ptr->sp_namp);
1819 if (rc != NS_LDAP_SUCCESS) {
1820 __s_cvt_freeEntryRdn(entry, rdn);
1821 return (rc);
1824 if (ptr->sp_pwdp == NULL) {
1825 __s_cvt_freeEntryRdn(entry, rdn);
1826 return (NS_LDAP_INVALID_PARAM);
1827 } else {
1828 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1829 if (rc != NS_LDAP_SUCCESS) {
1830 __s_cvt_freeEntryRdn(entry, rdn);
1831 return (rc);
1834 if (ptr->sp_lstchg >= 0) {
1835 (void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1836 rc = __s_add_attr(e, "shadowLastChange", ibuf);
1837 if (rc != NS_LDAP_SUCCESS) {
1838 __s_cvt_freeEntryRdn(entry, rdn);
1839 return (rc);
1842 if (ptr->sp_min >= 0) {
1843 (void) sprintf(ibuf, "%d", ptr->sp_min);
1844 rc = __s_add_attr(e, "shadowMin", ibuf);
1845 if (rc != NS_LDAP_SUCCESS) {
1846 __s_cvt_freeEntryRdn(entry, rdn);
1847 return (rc);
1850 if (ptr->sp_max >= 0) {
1851 (void) sprintf(ibuf, "%d", ptr->sp_max);
1852 rc = __s_add_attr(e, "shadowMax", ibuf);
1853 if (rc != NS_LDAP_SUCCESS) {
1854 __s_cvt_freeEntryRdn(entry, rdn);
1855 return (rc);
1858 if (ptr->sp_warn >= 0) {
1859 (void) sprintf(ibuf, "%d", ptr->sp_warn);
1860 rc = __s_add_attr(e, "shadowWarning", ibuf);
1861 if (rc != NS_LDAP_SUCCESS) {
1862 __s_cvt_freeEntryRdn(entry, rdn);
1863 return (rc);
1866 if (ptr->sp_inact >= 0) {
1867 (void) sprintf(ibuf, "%d", ptr->sp_inact);
1868 rc = __s_add_attr(e, "shadowInactive", ibuf);
1869 if (rc != NS_LDAP_SUCCESS) {
1870 __s_cvt_freeEntryRdn(entry, rdn);
1871 return (rc);
1874 if (ptr->sp_expire >= 0) {
1875 (void) sprintf(ibuf, "%d", ptr->sp_expire);
1876 rc = __s_add_attr(e, "shadowExpire", ibuf);
1877 if (rc != NS_LDAP_SUCCESS) {
1878 __s_cvt_freeEntryRdn(entry, rdn);
1879 return (rc);
1882 (void) sprintf(ibuf, "%d", ptr->sp_flag);
1883 rc = __s_add_attr(e, "shadowFlag", ibuf);
1884 if (rc != NS_LDAP_SUCCESS) {
1885 __s_cvt_freeEntryRdn(entry, rdn);
1886 return (rc);
1889 return (NS_LDAP_SUCCESS);
1894 * Conversion: group
1895 * Input format: struct group
1896 * Exported objectclass: posixGroup
1898 static int
1899 __s_cvt_group(const void *data, char **rdn,
1900 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1902 ns_ldap_entry_t *e;
1903 int rc;
1904 char trdn[RDNSIZE];
1905 /* routine specific */
1906 struct group *ptr;
1907 int i, j, k;
1908 char **nm, **lm;
1909 int max_attr = 4;
1910 char ibuf[10];
1911 static char *oclist[] = {
1912 "posixGroup",
1913 "top",
1914 NULL
1917 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1918 return (NS_LDAP_OP_FAILED);
1919 *entry = e = __s_mk_entry(oclist, max_attr);
1920 if (e == NULL)
1921 return (NS_LDAP_MEMORY);
1923 /* Convert the structure */
1924 ptr = (struct group *)data;
1926 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
1927 __ns_ldap_freeEntry(e);
1928 *entry = NULL;
1929 return (NS_LDAP_INVALID_PARAM);
1932 /* Create an appropriate rdn */
1933 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1934 *rdn = strdup(trdn);
1935 if (*rdn == NULL) {
1936 __ns_ldap_freeEntry(e);
1937 *entry = NULL;
1938 return (NS_LDAP_MEMORY);
1941 /* Error check the data and add the attributes */
1942 rc = __s_add_attr(e, "cn", ptr->gr_name);
1943 if (rc != NS_LDAP_SUCCESS) {
1944 __s_cvt_freeEntryRdn(entry, rdn);
1945 return (rc);
1948 (void) sprintf(ibuf, "%u", ptr->gr_gid);
1949 rc = __s_add_attr(e, "gidNumber", ibuf);
1950 if (rc != NS_LDAP_SUCCESS) {
1951 __s_cvt_freeEntryRdn(entry, rdn);
1952 return (rc);
1954 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1955 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1956 if (rc != NS_LDAP_SUCCESS) {
1957 __s_cvt_freeEntryRdn(entry, rdn);
1958 return (rc);
1962 if (ptr->gr_mem && ptr->gr_mem[0]) {
1963 lm = ptr->gr_mem;
1964 for (i = 0; *lm; i++, lm++)
1966 lm = ptr->gr_mem;
1967 nm = (char **)calloc(i+2, sizeof (char *));
1968 if (nm == NULL) {
1969 __s_cvt_freeEntryRdn(entry, rdn);
1970 return (NS_LDAP_MEMORY);
1972 for (j = 0; j < i; j++) {
1973 nm[j] = strdup(lm[j]);
1974 if (nm[j] == NULL) {
1975 for (k = 0; k < j; k++)
1976 free(nm[k]);
1977 free(nm);
1978 __s_cvt_freeEntryRdn(entry, rdn);
1979 return (NS_LDAP_MEMORY);
1982 rc = __s_add_attrlist(e, "memberUid", nm);
1983 for (j = 0; j < i; j++) {
1984 free(nm[j]);
1986 free(nm);
1987 nm = NULL;
1988 if (rc != NS_LDAP_SUCCESS) {
1989 __s_cvt_freeEntryRdn(entry, rdn);
1990 return (rc);
1994 return (NS_LDAP_SUCCESS);
1998 * Conversion: hosts
1999 * Input format: struct hostent
2000 * Exported objectclass: ipHost
2002 static int
2003 __s_cvt_hosts(const void *data, char **rdn,
2004 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2006 ns_ldap_entry_t *e;
2007 int rc;
2008 char trdn[RDNSIZE];
2009 /* routine specific */
2010 struct hostent *ptr;
2011 int max_attr = 6;
2012 int i, j, k;
2013 char **nm, **lm;
2014 static char *oclist[] = {
2015 "ipHost",
2016 "device",
2017 "top",
2018 NULL
2021 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2022 return (NS_LDAP_OP_FAILED);
2023 *entry = e = __s_mk_entry(oclist, max_attr);
2024 if (e == NULL)
2025 return (NS_LDAP_MEMORY);
2027 /* Convert the structure */
2028 ptr = (struct hostent *)data;
2030 if (ptr->h_name == NULL ||
2031 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == NULL) {
2032 __ns_ldap_freeEntry(e);
2033 *entry = NULL;
2034 return (NS_LDAP_INVALID_PARAM);
2037 /* Create an appropriate rdn */
2038 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
2039 ptr->h_name, ptr->h_addr_list[0]);
2040 *rdn = strdup(trdn);
2041 if (*rdn == NULL) {
2042 __ns_ldap_freeEntry(e);
2043 *entry = NULL;
2044 return (NS_LDAP_MEMORY);
2047 /* Error check the data and add the attributes */
2048 if (ptr->h_aliases && ptr->h_aliases[0]) {
2049 lm = ptr->h_aliases;
2051 * If there is a description, 'i' will contain
2052 * the index of the description in the aliases list
2054 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
2056 lm = ptr->h_aliases;
2057 nm = (char **)calloc(i+2, sizeof (char *));
2058 if (nm == NULL) {
2059 __s_cvt_freeEntryRdn(entry, rdn);
2060 return (NS_LDAP_MEMORY);
2062 nm[0] = ptr->h_name;
2063 for (j = 0; j < i; j++)
2064 nm[j+1] = ptr->h_aliases[j];
2066 rc = __s_add_attrlist(e, "cn", nm);
2068 if (rc != NS_LDAP_SUCCESS) {
2069 __s_cvt_freeEntryRdn(entry, rdn);
2070 free(nm);
2071 return (rc);
2074 if (lm[i] && lm[i][0] == '#') {
2075 nm[0] = &(lm[i][1]);
2076 nm[1] = NULL;
2077 rc = __s_add_attrlist(e, "description", nm);
2079 free(nm);
2080 nm = NULL;
2081 if (rc != NS_LDAP_SUCCESS) {
2082 __s_cvt_freeEntryRdn(entry, rdn);
2083 return (rc);
2085 } else {
2086 rc = __s_add_attr(e, "cn", ptr->h_name);
2087 if (rc != NS_LDAP_SUCCESS) {
2088 __s_cvt_freeEntryRdn(entry, rdn);
2089 return (rc);
2093 if (ptr->h_addr_list && ptr->h_addr_list[0]) {
2094 lm = ptr->h_addr_list;
2095 for (i = 0; *lm; i++, lm++)
2097 lm = ptr->h_addr_list;
2098 nm = (char **)calloc(i+2, sizeof (char *));
2099 if (nm == NULL) {
2100 __s_cvt_freeEntryRdn(entry, rdn);
2101 return (NS_LDAP_MEMORY);
2103 for (j = 0; j < i; j++) {
2104 nm[j] = strdup(lm[j]);
2105 if (nm[j] == NULL) {
2106 for (k = 0; k < j; k++)
2107 free(nm[k]);
2108 free(nm);
2109 __s_cvt_freeEntryRdn(entry, rdn);
2110 return (NS_LDAP_MEMORY);
2113 rc = __s_add_attrlist(e, "ipHostNumber", nm);
2114 for (j = 0; j < i; j++) {
2115 free(nm[j]);
2117 free(nm);
2118 nm = NULL;
2119 if (rc != NS_LDAP_SUCCESS) {
2120 __s_cvt_freeEntryRdn(entry, rdn);
2121 return (rc);
2123 } else {
2124 __s_cvt_freeEntryRdn(entry, rdn);
2125 return (NS_LDAP_INVALID_PARAM);
2128 return (NS_LDAP_SUCCESS);
2132 * Conversion: rpc
2133 * Input format: struct rpcent
2134 * Exported objectclass: oncRpc
2136 static int
2137 __s_cvt_rpc(const void *data, char **rdn,
2138 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2140 ns_ldap_entry_t *e;
2141 int rc;
2142 char trdn[RDNSIZE];
2143 /* routine specific */
2144 struct rpcent *ptr;
2145 int max_attr = 3;
2146 int i, j;
2147 char **nm;
2148 char ibuf[10];
2149 static char *oclist[] = {
2150 "oncRpc",
2151 "top",
2152 NULL
2155 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2156 return (NS_LDAP_OP_FAILED);
2157 *entry = e = __s_mk_entry(oclist, max_attr);
2158 if (e == NULL)
2159 return (NS_LDAP_MEMORY);
2161 /* Convert the structure */
2162 ptr = (struct rpcent *)data;
2164 if (ptr->r_name == NULL || ptr->r_number < 0) {
2165 __ns_ldap_freeEntry(e);
2166 *entry = NULL;
2167 return (NS_LDAP_INVALID_PARAM);
2170 /* Create an appropriate rdn */
2171 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
2172 *rdn = strdup(trdn);
2173 if (*rdn == NULL) {
2174 __ns_ldap_freeEntry(e);
2175 *entry = NULL;
2176 return (NS_LDAP_MEMORY);
2179 /* Error check the data and add the attributes */
2180 if (ptr->r_aliases && ptr->r_aliases[0]) {
2181 nm = ptr->r_aliases;
2182 for (i = 0; *nm; i++, nm++)
2184 nm = (char **)calloc(i+2, sizeof (char *));
2185 if (nm == NULL) {
2186 __s_cvt_freeEntryRdn(entry, rdn);
2187 return (NS_LDAP_MEMORY);
2189 nm[0] = ptr->r_name;
2190 for (j = 0; j < i; j++)
2191 nm[j+1] = ptr->r_aliases[j];
2193 rc = __s_add_attrlist(e, "cn", nm);
2194 free(nm);
2195 nm = NULL;
2196 if (rc != NS_LDAP_SUCCESS) {
2197 __s_cvt_freeEntryRdn(entry, rdn);
2198 return (rc);
2200 } else {
2201 rc = __s_add_attr(e, "cn", ptr->r_name);
2202 if (rc != NS_LDAP_SUCCESS) {
2203 __s_cvt_freeEntryRdn(entry, rdn);
2204 return (rc);
2208 if (ptr->r_number >= 0) {
2209 (void) sprintf(ibuf, "%d", ptr->r_number);
2210 rc = __s_add_attr(e, "oncRpcNumber", ibuf);
2211 if (rc != NS_LDAP_SUCCESS) {
2212 __s_cvt_freeEntryRdn(entry, rdn);
2213 return (rc);
2217 return (NS_LDAP_SUCCESS);
2222 * Conversion: protocols
2223 * Input format: struct protoent
2224 * Exported objectclass: ipProtocol
2226 static int
2227 __s_cvt_protocols(const void *data, char **rdn,
2228 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2230 ns_ldap_entry_t *e;
2231 int rc;
2232 char trdn[RDNSIZE];
2233 /* routine specific */
2234 struct protoent *ptr;
2235 int max_attr = 3;
2236 int i, j;
2237 char ibuf[10];
2238 char **nm;
2239 static char *oclist[] = {
2240 "ipProtocol",
2241 "top",
2242 NULL
2245 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2246 return (NS_LDAP_OP_FAILED);
2247 *entry = e = __s_mk_entry(oclist, max_attr);
2248 if (e == NULL)
2249 return (NS_LDAP_MEMORY);
2251 /* Convert the structure */
2252 ptr = (struct protoent *)data;
2254 if (ptr->p_name == NULL || ptr->p_proto < 0) {
2255 __ns_ldap_freeEntry(e);
2256 *entry = NULL;
2257 return (NS_LDAP_INVALID_PARAM);
2260 /* Create an appropriate rdn */
2261 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
2262 *rdn = strdup(trdn);
2263 if (*rdn == NULL) {
2264 __ns_ldap_freeEntry(e);
2265 *entry = NULL;
2266 return (NS_LDAP_MEMORY);
2269 /* Error check the data and add the attributes */
2270 if (ptr->p_aliases && ptr->p_aliases[0]) {
2271 nm = ptr->p_aliases;
2272 for (i = 0; *nm; i++, nm++)
2274 nm = (char **)calloc(i+2, sizeof (char *));
2275 if (nm == NULL) {
2276 __s_cvt_freeEntryRdn(entry, rdn);
2277 return (NS_LDAP_MEMORY);
2279 nm[0] = ptr->p_name;
2280 for (j = 0; j < i; j++)
2281 nm[j+1] = ptr->p_aliases[j];
2283 rc = __s_add_attrlist(e, "cn", nm);
2284 free(nm);
2285 nm = NULL;
2286 if (rc != NS_LDAP_SUCCESS) {
2287 __s_cvt_freeEntryRdn(entry, rdn);
2288 return (rc);
2290 } else {
2291 rc = __s_add_attr(e, "cn", ptr->p_name);
2292 if (rc != NS_LDAP_SUCCESS) {
2293 __s_cvt_freeEntryRdn(entry, rdn);
2294 return (rc);
2298 (void) sprintf(ibuf, "%d", ptr->p_proto);
2299 rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
2300 if (rc != NS_LDAP_SUCCESS) {
2301 __s_cvt_freeEntryRdn(entry, rdn);
2302 return (rc);
2305 return (NS_LDAP_SUCCESS);
2310 * Conversion: services
2311 * Input format: struct servent
2312 * Exported objectclass: ipService
2314 static int
2315 __s_cvt_services(const void *data, char **rdn,
2316 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2318 ns_ldap_entry_t *e;
2319 int rc;
2320 char trdn[RDNSIZE];
2321 char esc_str[RDNSIZE];
2322 /* routine specific */
2323 struct servent *ptr;
2324 int max_attr = 4;
2325 int i, j;
2326 char ibuf[10];
2327 char **nm;
2328 static char *oclist[] = {
2329 "ipService",
2330 "top",
2331 NULL
2334 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2335 return (NS_LDAP_OP_FAILED);
2336 *entry = e = __s_mk_entry(oclist, max_attr);
2337 if (e == NULL)
2338 return (NS_LDAP_MEMORY);
2340 /* Convert the structure */
2341 ptr = (struct servent *)data;
2343 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == NULL) {
2344 __ns_ldap_freeEntry(e);
2345 *entry = NULL;
2346 return (NS_LDAP_INVALID_PARAM);
2350 * Escape special characters in service name.
2352 if (escape_str(esc_str, ptr->s_name) != 0) {
2353 __ns_ldap_freeEntry(e);
2354 *entry = NULL;
2355 return (NS_LDAP_INVALID_PARAM);
2358 /* Create an appropriate rdn */
2359 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
2360 esc_str, ptr->s_proto);
2362 *rdn = strdup(trdn);
2363 if (*rdn == NULL) {
2364 __ns_ldap_freeEntry(e);
2365 *entry = NULL;
2366 return (NS_LDAP_MEMORY);
2369 /* Error check the data and add the attributes */
2370 if (ptr->s_aliases && ptr->s_aliases[0]) {
2371 nm = ptr->s_aliases;
2372 for (i = 0; *nm; i++, nm++)
2374 nm = (char **)calloc(i+2, sizeof (char *));
2375 if (nm == NULL) {
2376 __s_cvt_freeEntryRdn(entry, rdn);
2377 return (NS_LDAP_MEMORY);
2379 nm[0] = ptr->s_name;
2380 for (j = 0; j < i; j++)
2381 nm[j+1] = ptr->s_aliases[j];
2383 rc = __s_add_attrlist(e, "cn", nm);
2384 free(nm);
2385 nm = NULL;
2386 if (rc != NS_LDAP_SUCCESS) {
2387 __s_cvt_freeEntryRdn(entry, rdn);
2388 return (rc);
2390 } else {
2391 rc = __s_add_attr(e, "cn", ptr->s_name);
2392 if (rc != NS_LDAP_SUCCESS) {
2393 __s_cvt_freeEntryRdn(entry, rdn);
2394 return (rc);
2398 (void) sprintf(ibuf, "%d", ptr->s_port);
2399 rc = __s_add_attr(e, "ipServicePort", ibuf);
2400 if (rc != NS_LDAP_SUCCESS) {
2401 __s_cvt_freeEntryRdn(entry, rdn);
2402 return (rc);
2404 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
2405 if (rc != NS_LDAP_SUCCESS) {
2406 __s_cvt_freeEntryRdn(entry, rdn);
2407 return (rc);
2410 return (NS_LDAP_SUCCESS);
2414 * Conversion: networks
2415 * Input format: struct netent
2416 * Exported objectclass: ipNetwork
2418 static int
2419 __s_cvt_networks(const void *data, char **rdn,
2420 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2422 ns_ldap_entry_t *e;
2423 int rc;
2424 char trdn[RDNSIZE];
2425 /* routine specific */
2426 struct netent *ptr;
2427 int max_attr = 4;
2428 int i, j;
2429 char cp[64];
2430 char **nm;
2431 static char *oclist[] = {
2432 "ipNetwork",
2433 "top",
2434 NULL
2437 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2438 return (NS_LDAP_OP_FAILED);
2439 *entry = e = __s_mk_entry(oclist, max_attr);
2440 if (e == NULL)
2441 return (NS_LDAP_MEMORY);
2443 /* Convert the structure */
2444 ptr = (struct netent *)data;
2446 if (ptr->n_name == NULL || ptr->n_net == 0) {
2447 __ns_ldap_freeEntry(e);
2448 *entry = NULL;
2449 return (NS_LDAP_INVALID_PARAM);
2452 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2453 (ptr->n_net & 0xFF000000) >> 24,
2454 (ptr->n_net & 0x00FF0000) >> 16,
2455 (ptr->n_net & 0x0000FF00) >> 8,
2456 (ptr->n_net & 0x000000FF));
2458 /* Create an appropriate rdn */
2459 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2460 *rdn = strdup(trdn);
2461 if (*rdn == NULL) {
2462 __ns_ldap_freeEntry(e);
2463 *entry = NULL;
2464 return (NS_LDAP_MEMORY);
2467 /* Error check the data and add the attributes */
2468 if (ptr->n_aliases && ptr->n_aliases[0]) {
2469 nm = ptr->n_aliases;
2470 for (i = 0; *nm; i++, nm++)
2472 nm = (char **)calloc(i+2, sizeof (char *));
2473 if (nm == NULL) {
2474 __s_cvt_freeEntryRdn(entry, rdn);
2475 return (NS_LDAP_MEMORY);
2477 nm[0] = ptr->n_name;
2478 for (j = 0; j < i; j++)
2479 nm[j+1] = ptr->n_aliases[j];
2481 rc = __s_add_attrlist(e, "cn", nm);
2482 free(nm);
2483 nm = NULL;
2484 if (rc != NS_LDAP_SUCCESS) {
2485 __s_cvt_freeEntryRdn(entry, rdn);
2486 return (rc);
2488 } else {
2489 rc = __s_add_attr(e, "cn", ptr->n_name);
2490 if (rc != NS_LDAP_SUCCESS) {
2491 __s_cvt_freeEntryRdn(entry, rdn);
2492 return (rc);
2496 rc = __s_add_attr(e, "ipNetworkNumber", cp);
2497 if (rc != NS_LDAP_SUCCESS) {
2498 __s_cvt_freeEntryRdn(entry, rdn);
2499 return (rc);
2502 return (NS_LDAP_SUCCESS);
2506 * Conversion: netmasks
2507 * Input format: struct _ns_netmasks
2508 * Exported objectclass: ipNetwork
2510 static int
2511 __s_cvt_netmasks(const void *data, char **rdn,
2512 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2514 ns_ldap_entry_t *e;
2515 int rc;
2516 char trdn[RDNSIZE];
2517 /* routine specific */
2518 struct _ns_netmasks *ptr;
2519 int max_attr = 4;
2520 static char *oclist[] = {
2521 "ipNetwork",
2522 "top",
2523 NULL
2526 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2527 return (NS_LDAP_OP_FAILED);
2528 *entry = e = __s_mk_entry(oclist, max_attr);
2529 if (e == NULL)
2530 return (NS_LDAP_MEMORY);
2532 /* Convert the structure */
2533 ptr = (struct _ns_netmasks *)data;
2535 if (ptr->netnumber == NULL) {
2536 __ns_ldap_freeEntry(e);
2537 *entry = NULL;
2538 return (NS_LDAP_INVALID_PARAM);
2541 /* Create an appropriate rdn */
2542 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2543 *rdn = strdup(trdn);
2544 if (*rdn == NULL) {
2545 __ns_ldap_freeEntry(e);
2546 *entry = NULL;
2547 return (NS_LDAP_MEMORY);
2550 /* Error check the data and add the attributes */
2551 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2552 if (rc != NS_LDAP_SUCCESS) {
2553 __s_cvt_freeEntryRdn(entry, rdn);
2554 return (rc);
2557 if (ptr->netmask != NULL) {
2558 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2559 if (rc != NS_LDAP_SUCCESS) {
2560 __s_cvt_freeEntryRdn(entry, rdn);
2561 return (rc);
2565 return (NS_LDAP_SUCCESS);
2569 * Conversion: netgroups
2570 * Input format: struct _ns_netgroups
2571 * Exported objectclass: nisNetgroup
2573 static int
2574 __s_cvt_netgroups(const void *data, char **rdn,
2575 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2577 ns_ldap_entry_t *e;
2578 int rc;
2579 char trdn[RDNSIZE];
2580 /* routine specific */
2581 struct _ns_netgroups *ptr;
2582 int max_attr = 6;
2583 int i, j;
2584 char **nm;
2585 static char *oclist[] = {
2586 "nisNetgroup",
2587 "top",
2588 NULL
2591 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2592 return (NS_LDAP_OP_FAILED);
2593 *entry = e = __s_mk_entry(oclist, max_attr);
2594 if (e == NULL)
2595 return (NS_LDAP_MEMORY);
2597 /* Convert the structure */
2598 ptr = (struct _ns_netgroups *)data;
2600 if (ptr->name == NULL || *ptr->name == '\0') {
2601 __ns_ldap_freeEntry(e);
2602 *entry = NULL;
2603 return (NS_LDAP_INVALID_PARAM);
2606 /* Create an appropriate rdn */
2607 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2608 *rdn = strdup(trdn);
2609 if (*rdn == NULL) {
2610 __ns_ldap_freeEntry(e);
2611 *entry = NULL;
2612 return (NS_LDAP_MEMORY);
2615 rc = __s_add_attr(e, "cn", ptr->name);
2616 if (rc != NS_LDAP_SUCCESS) {
2617 __s_cvt_freeEntryRdn(entry, rdn);
2618 return (rc);
2621 /* Error check the data and add the attributes */
2622 if (ptr->triplet && ptr->triplet[0]) {
2623 nm = ptr->triplet;
2624 for (i = 0; *nm; i++, nm++)
2626 nm = (char **)calloc(i+2, sizeof (char *));
2627 if (nm == NULL) {
2628 __s_cvt_freeEntryRdn(entry, rdn);
2629 return (NS_LDAP_MEMORY);
2631 for (j = 0; j < i; j++)
2632 nm[j] = ptr->triplet[j];
2634 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
2635 free(nm);
2636 nm = NULL;
2637 if (rc != NS_LDAP_SUCCESS) {
2638 __s_cvt_freeEntryRdn(entry, rdn);
2639 return (rc);
2642 if (ptr->netgroup && ptr->netgroup[0]) {
2643 nm = ptr->netgroup;
2644 for (i = 0; *nm; i++, nm++)
2646 nm = (char **)calloc(i+2, sizeof (char *));
2647 if (nm == NULL) {
2648 __s_cvt_freeEntryRdn(entry, rdn);
2649 return (NS_LDAP_MEMORY);
2651 for (j = 0; j < i; j++)
2652 nm[j] = ptr->netgroup[j];
2654 rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
2655 free(nm);
2656 nm = NULL;
2657 if (rc != NS_LDAP_SUCCESS) {
2658 __s_cvt_freeEntryRdn(entry, rdn);
2659 return (rc);
2662 return (NS_LDAP_SUCCESS);
2665 * Conversion: bootparams
2666 * Input format: struct _ns_bootp
2667 * Exported objectclass: bootableDevice, device
2669 static int
2670 __s_cvt_bootparams(const void *data, char **rdn,
2671 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2673 ns_ldap_entry_t *e;
2674 int rc;
2675 char trdn[RDNSIZE];
2676 /* routine specific */
2677 struct _ns_bootp *ptr;
2678 int max_attr = 4;
2679 int i, j;
2680 char **nm;
2681 static char *oclist[] = {
2682 "bootableDevice",
2683 "device",
2684 "top",
2685 NULL
2688 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2689 return (NS_LDAP_OP_FAILED);
2690 *entry = e = __s_mk_entry(oclist, max_attr);
2691 if (e == NULL)
2692 return (NS_LDAP_MEMORY);
2694 /* Convert the structure */
2695 ptr = (struct _ns_bootp *)data;
2697 if (ptr->name == NULL || *ptr->name == '\0') {
2698 __ns_ldap_freeEntry(e);
2699 *entry = NULL;
2700 return (NS_LDAP_INVALID_PARAM);
2703 /* Create an appropriate rdn */
2704 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2705 *rdn = strdup(trdn);
2706 if (*rdn == NULL) {
2707 __ns_ldap_freeEntry(e);
2708 *entry = NULL;
2709 return (NS_LDAP_MEMORY);
2712 rc = __s_add_attr(e, "cn", ptr->name);
2713 if (rc != NS_LDAP_SUCCESS) {
2714 __s_cvt_freeEntryRdn(entry, rdn);
2715 return (rc);
2718 /* Error check the data and add the attributes */
2719 if (ptr->param && ptr->param[0]) {
2720 nm = ptr->param;
2721 for (i = 0; *nm; i++, nm++)
2723 nm = (char **)calloc(i+2, sizeof (char *));
2724 if (nm == NULL) {
2725 __s_cvt_freeEntryRdn(entry, rdn);
2726 return (NS_LDAP_MEMORY);
2728 for (j = 0; j < i; j++)
2729 nm[j] = ptr->param[j];
2731 rc = __s_add_attrlist(e, "bootParameter", nm);
2732 free(nm);
2733 nm = NULL;
2734 if (rc != NS_LDAP_SUCCESS) {
2735 __s_cvt_freeEntryRdn(entry, rdn);
2736 return (rc);
2740 return (NS_LDAP_SUCCESS);
2744 * Conversion: ethers
2745 * Input format: struct _ns_ethers
2746 * Exported objectclass: ieee802Device, device
2748 static int
2749 __s_cvt_ethers(const void *data, char **rdn,
2750 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2752 ns_ldap_entry_t *e;
2753 int rc;
2754 char trdn[RDNSIZE];
2755 /* routine specific */
2756 struct _ns_ethers *ptr;
2757 int max_attr = 4;
2758 static char *oclist[] = {
2759 "ieee802Device",
2760 "device",
2761 "top",
2762 NULL
2765 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2766 return (NS_LDAP_OP_FAILED);
2767 *entry = e = __s_mk_entry(oclist, max_attr);
2768 if (e == NULL)
2769 return (NS_LDAP_MEMORY);
2771 /* Convert the structure */
2772 ptr = (struct _ns_ethers *)data;
2774 if (ptr->name == NULL || *ptr->name == '\0' || ptr->ether == NULL) {
2775 __ns_ldap_freeEntry(e);
2776 *entry = NULL;
2777 return (NS_LDAP_INVALID_PARAM);
2780 /* Create an appropriate rdn */
2781 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2782 *rdn = strdup(trdn);
2783 if (*rdn == NULL) {
2784 __ns_ldap_freeEntry(e);
2785 *entry = NULL;
2786 return (NS_LDAP_MEMORY);
2789 /* Error check the data and add the attributes */
2790 rc = __s_add_attr(e, "cn", ptr->name);
2791 if (rc != NS_LDAP_SUCCESS) {
2792 __s_cvt_freeEntryRdn(entry, rdn);
2793 return (rc);
2796 rc = __s_add_attr(e, "macAddress", ptr->ether);
2797 if (rc != NS_LDAP_SUCCESS) {
2798 __s_cvt_freeEntryRdn(entry, rdn);
2799 return (rc);
2802 return (NS_LDAP_SUCCESS);
2805 * This function is used when processing an ethers (objectclass: ieee802Device)
2806 * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2807 * already found in LDAP. Since both ethers and bootparams share the same
2808 * LDAP container, we want to check that the entry found in LDAP is:
2809 * - either the same entry (same cn, same objectclass): we don't do anything
2810 * in this case
2811 * - or an entry which does not have the objectclass we are interesting in:
2812 * in this case, we modify the existing entry by adding the relevant
2813 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2814 * from the attribute list previously computing by the relevant conversion
2815 * function.
2816 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams()
2817 * we know that there is only 1 more attribute today to add (macAddress
2818 * or bootParameter)
2820 #define _MAX_ATTR_ETHBOOTP 2
2821 static int
2822 modify_ethers_bootp(
2823 const char *service,
2824 const char *rdn,
2825 const char *fulldn,
2826 const ns_ldap_attr_t * const *attrlist,
2827 const ns_cred_t *cred,
2828 const int flags,
2829 ns_ldap_error_t **errorp)
2831 char filter[BUFSIZ];
2832 ns_ldap_result_t *resultp;
2833 int rc = 0;
2834 int i;
2835 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2836 ns_ldap_attr_t new_attrlist0;
2837 char *new_attrvalue0[1];
2838 const ns_ldap_attr_t * const *aptr = attrlist;
2839 ns_ldap_attr_t *aptr2;
2840 ns_ldap_error_t *new_errorp = NULL;
2842 if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2843 errorp == NULL || service == NULL)
2844 return (NS_LDAP_OP_FAILED);
2846 bzero(&new_attrlist, sizeof (new_attrlist));
2847 bzero(&new_attrlist0, sizeof (new_attrlist0));
2848 new_attrlist[0] = &new_attrlist0;
2849 new_attrlist[0]->attrvalue = new_attrvalue0;
2851 new_attrlist[0]->attrname = "objectclass";
2852 new_attrlist[0]->value_count = 1;
2853 if (strcasecmp(service, "ethers") == 0) {
2854 (void) snprintf(&filter[0], sizeof (filter),
2855 "(&(objectClass=ieee802Device)(%s))", rdn);
2856 new_attrlist[0]->attrvalue[0] = "ieee802Device";
2857 } else {
2858 (void) snprintf(&filter[0], sizeof (filter),
2859 "(&(objectClass=bootableDevice)(%s))", rdn);
2860 new_attrlist[0]->attrvalue[0] = "bootableDevice";
2863 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2864 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2865 NULL, NULL);
2867 switch (rc) {
2868 case NS_LDAP_SUCCESS:
2870 * entry already exists for this service
2871 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2873 rc = NS_LDAP_INTERNAL;
2874 break;
2875 case NS_LDAP_NOTFOUND:
2877 * entry not found with the given objectclasss but entry exists
2878 * hence add the relevant attribute (macAddress or bootparams).
2880 i = 1;
2881 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2882 /* aptr2 needed here to avoid lint warning */
2883 aptr2 = (ns_ldap_attr_t *)*aptr++;
2884 if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2885 (strcasecmp(aptr2->attrname,
2886 "objectclass") != 0)) {
2887 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
2891 if (i != _MAX_ATTR_ETHBOOTP) {
2892 /* we haven't found all expected attributes */
2893 rc = NS_LDAP_OP_FAILED;
2894 break;
2897 aptr = (const ns_ldap_attr_t * const *) new_attrlist;
2898 /* clean errorp first */
2899 (void) __ns_ldap_freeError(errorp);
2900 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2901 errorp);
2902 break;
2903 default:
2905 * unexpected error happenned
2906 * returning relevant error
2908 (void) __ns_ldap_freeError(errorp);
2909 *errorp = new_errorp;
2910 break;
2913 return (rc);
2917 * Conversion: publickey
2918 * Input format: struct _ns_pubkey
2919 * Exported objectclass: NisKeyObject
2921 static int
2922 __s_cvt_publickey(const void *data, char **rdn,
2923 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2925 ns_ldap_entry_t *e;
2926 int rc;
2927 char trdn[RDNSIZE];
2928 /* routine specific */
2929 struct _ns_pubkey *ptr;
2930 int max_attr = 3;
2931 static char *oclist[] = {
2932 "NisKeyObject",
2933 NULL
2936 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2937 return (NS_LDAP_OP_FAILED);
2938 *entry = e = __s_mk_entry(oclist, max_attr);
2939 if (e == NULL)
2940 return (NS_LDAP_MEMORY);
2942 /* Convert the structure */
2943 ptr = (struct _ns_pubkey *)data;
2945 if (ptr->name == NULL || *ptr->name == '\0' || ptr->pubkey == NULL ||
2946 ptr->privkey == NULL) {
2947 __ns_ldap_freeEntry(e);
2948 *entry = NULL;
2949 return (NS_LDAP_INVALID_PARAM);
2952 /* Create an appropriate rdn */
2953 if (ptr->hostcred == NS_HOSTCRED_FALSE)
2954 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2955 else
2956 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2957 *rdn = strdup(trdn);
2958 if (*rdn == NULL) {
2959 __ns_ldap_freeEntry(e);
2960 *entry = NULL;
2961 return (NS_LDAP_MEMORY);
2964 /* Error check the data and add the attributes */
2966 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2967 if (rc != NS_LDAP_SUCCESS) {
2968 __s_cvt_freeEntryRdn(entry, rdn);
2969 return (rc);
2972 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2973 if (rc != NS_LDAP_SUCCESS) {
2974 __s_cvt_freeEntryRdn(entry, rdn);
2975 return (rc);
2978 return (NS_LDAP_SUCCESS);
2981 * Conversion: aliases
2982 * Input format: struct _ns_alias
2983 * Exported objectclass: mailGroup
2985 static int
2986 __s_cvt_aliases(const void *data, char **rdn,
2987 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2989 ns_ldap_entry_t *e;
2990 int rc;
2991 char trdn[RDNSIZE];
2992 /* routine specific */
2993 struct _ns_alias *ptr;
2994 int max_attr = 4;
2995 int i, j;
2996 char **nm;
2997 static char *oclist[] = {
2998 "mailGroup",
2999 "top",
3000 NULL
3003 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3004 return (NS_LDAP_OP_FAILED);
3005 *entry = e = __s_mk_entry(oclist, max_attr);
3006 if (e == NULL)
3007 return (NS_LDAP_MEMORY);
3009 /* Convert the structure */
3010 ptr = (struct _ns_alias *)data;
3012 if (ptr->alias == NULL || *ptr->alias == '\0') {
3013 __ns_ldap_freeEntry(e);
3014 *entry = NULL;
3015 return (NS_LDAP_INVALID_PARAM);
3018 /* Create an appropriate rdn */
3019 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
3020 *rdn = strdup(trdn);
3021 if (*rdn == NULL) {
3022 __ns_ldap_freeEntry(e);
3023 *entry = NULL;
3024 return (NS_LDAP_MEMORY);
3027 rc = __s_add_attr(e, "mail", (char *)ptr->alias);
3028 if (rc != NS_LDAP_SUCCESS) {
3029 __s_cvt_freeEntryRdn(entry, rdn);
3030 return (rc);
3033 /* Error check the data and add the attributes */
3034 if (ptr->member && ptr->member[0]) {
3035 nm = ptr->member;
3036 for (i = 0; *nm; i++, nm++)
3038 nm = (char **)calloc(i+2, sizeof (char *));
3039 if (nm == NULL) {
3040 __s_cvt_freeEntryRdn(entry, rdn);
3041 return (NS_LDAP_MEMORY);
3043 for (j = 0; j < i; j++)
3044 nm[j] = ptr->member[j];
3046 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
3047 free(nm);
3048 nm = NULL;
3049 if (rc != NS_LDAP_SUCCESS) {
3050 __s_cvt_freeEntryRdn(entry, rdn);
3051 return (rc);
3055 return (NS_LDAP_SUCCESS);
3059 * Conversion: automount
3060 * Input format: struct _ns_automount
3061 * Exported objectclass: automount
3063 static int
3064 __s_cvt_auto_mount(const void *data, char **rdn,
3065 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3067 ns_ldap_entry_t *e;
3068 int rc;
3069 char trdn[RDNSIZE];
3070 /* routine specific */
3071 struct _ns_automount *ptr;
3072 int max_attr = 6;
3073 void **paramVal = NULL;
3074 char **mappedschema = NULL;
3075 int version1 = 0;
3076 static char *oclist[] = {
3077 NULL,
3078 "top",
3079 NULL
3082 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3083 return (NS_LDAP_OP_FAILED);
3085 /* determine profile version number */
3086 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal, errorp);
3087 if (paramVal && *paramVal &&
3088 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
3089 version1 = 1;
3090 if (paramVal)
3091 (void) __ns_ldap_freeParam(&paramVal);
3092 if (rc && errorp)
3093 (void) __ns_ldap_freeError(errorp);
3095 /* use old schema for version 1 profiles */
3096 if (version1)
3097 oclist[0] = "nisObject";
3098 else
3099 oclist[0] = "automount";
3101 *entry = e = __s_mk_entry(oclist, max_attr);
3102 if (e == NULL)
3103 return (NS_LDAP_MEMORY);
3105 /* Convert the structure */
3106 ptr = (struct _ns_automount *)data;
3108 if (ptr->key == NULL || *ptr->key == '\0' || ptr->value == NULL ||
3109 ptr->mapname == NULL) {
3110 __ns_ldap_freeEntry(e);
3111 *entry = NULL;
3112 return (NS_LDAP_INVALID_PARAM);
3115 /* Create an appropriate rdn */
3116 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
3117 ptr->key);
3118 *rdn = strdup(trdn);
3119 if (*rdn == NULL) {
3120 __ns_ldap_freeEntry(e);
3121 *entry = NULL;
3122 return (NS_LDAP_MEMORY);
3125 rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
3126 (char *)ptr->key);
3127 if (rc != NS_LDAP_SUCCESS) {
3128 __s_cvt_freeEntryRdn(entry, rdn);
3129 return (rc);
3132 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
3133 (char *)ptr->value);
3134 if (rc != NS_LDAP_SUCCESS) {
3135 __s_cvt_freeEntryRdn(entry, rdn);
3136 return (rc);
3140 * even for version 2, if automount is mapped to nisObject we
3141 * still need 'nisMapName' attribute
3143 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
3144 if (mappedschema && mappedschema[0] &&
3145 strcasecmp(mappedschema[0], "nisObject") == 0)
3146 version1 = 1;
3147 if (mappedschema)
3148 __s_api_free2dArray(mappedschema);
3150 if (version1) {
3151 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
3152 if (rc != NS_LDAP_SUCCESS) {
3153 __s_cvt_freeEntryRdn(entry, rdn);
3154 return (rc);
3158 return (NS_LDAP_SUCCESS);
3161 * Conversion: auth_attr
3162 * Input format: authstr_t
3163 * Exported objectclass: SolarisAuthAttr
3165 static int
3166 __s_cvt_authattr(const void *data, char **rdn,
3167 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3169 ns_ldap_entry_t *e;
3170 int rc;
3171 char trdn[RDNSIZE];
3172 /* routine specific */
3173 authstr_t *ptr;
3174 int max_attr = 6;
3175 static char *oclist[] = {
3176 "SolarisAuthAttr",
3177 "top",
3178 NULL
3181 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3182 return (NS_LDAP_OP_FAILED);
3184 *entry = e = __s_mk_entry(oclist, max_attr);
3185 if (e == NULL)
3186 return (NS_LDAP_MEMORY);
3188 /* Convert the structure */
3189 ptr = (authstr_t *)data;
3191 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3192 __ns_ldap_freeEntry(e);
3193 *entry = NULL;
3194 return (NS_LDAP_INVALID_PARAM);
3197 /* Create an appropriate rdn */
3198 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3199 *rdn = strdup(trdn);
3200 if (*rdn == NULL) {
3201 __ns_ldap_freeEntry(e);
3202 *entry = NULL;
3203 return (NS_LDAP_MEMORY);
3206 rc = __s_add_attr(e, "cn", ptr->name);
3207 if (rc != NS_LDAP_SUCCESS) {
3208 __s_cvt_freeEntryRdn(entry, rdn);
3209 return (rc);
3212 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3213 if (rc != NS_LDAP_SUCCESS) {
3214 __s_cvt_freeEntryRdn(entry, rdn);
3215 return (rc);
3218 if (ptr->res1 != NULL) {
3219 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3220 if (rc != NS_LDAP_SUCCESS) {
3221 __s_cvt_freeEntryRdn(entry, rdn);
3222 return (rc);
3226 if (ptr->res2 != NULL) {
3227 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3228 if (rc != NS_LDAP_SUCCESS) {
3229 __s_cvt_freeEntryRdn(entry, rdn);
3230 return (rc);
3234 if (ptr->short_desc != NULL) {
3235 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
3236 if (rc != NS_LDAP_SUCCESS) {
3237 __s_cvt_freeEntryRdn(entry, rdn);
3238 return (rc);
3242 if (ptr->long_desc != NULL) {
3243 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
3244 if (rc != NS_LDAP_SUCCESS) {
3245 __s_cvt_freeEntryRdn(entry, rdn);
3246 return (rc);
3250 return (NS_LDAP_SUCCESS);
3253 * Conversion: exec_attr
3254 * Input format: execstr_t
3255 * Exported objectclass: SolarisExecAttr
3257 static int
3258 __s_cvt_execattr(const void *data, char **rdn,
3259 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3261 ns_ldap_entry_t *e;
3262 int rc;
3263 char trdn[RDNSIZE];
3264 char esc_str[RDNSIZE];
3265 /* routine specific */
3266 execstr_t *ptr;
3267 int max_attr = 7;
3268 static char *oclist[] = {
3269 "SolarisExecAttr",
3270 "SolarisProfAttr",
3271 "top",
3272 NULL
3275 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3276 return (NS_LDAP_OP_FAILED);
3278 *entry = e = __s_mk_entry(oclist, max_attr);
3279 if (e == NULL)
3280 return (NS_LDAP_MEMORY);
3282 /* Convert the structure */
3283 ptr = (execstr_t *)data;
3285 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3286 ptr->policy == NULL || ptr->policy[0] == '\0' ||
3287 ptr->type == NULL || ptr->type[0] == '\0' ||
3288 ptr->id == NULL || ptr->id[0] == '\0') {
3289 __ns_ldap_freeEntry(e);
3290 *entry = NULL;
3291 return (NS_LDAP_INVALID_PARAM);
3295 * Escape special characters in ProfileID.
3297 if (escape_str(esc_str, ptr->id) != 0) {
3298 __ns_ldap_freeEntry(e);
3299 *entry = NULL;
3300 return (NS_LDAP_INVALID_PARAM);
3303 /* Create an appropriate rdn */
3304 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
3305 "+SolarisProfileType=%s+SolarisProfileId=%s",
3306 ptr->name, ptr->policy, ptr->type, esc_str);
3308 *rdn = strdup(trdn);
3309 if (*rdn == NULL) {
3310 __ns_ldap_freeEntry(e);
3311 *entry = NULL;
3312 return (NS_LDAP_MEMORY);
3315 rc = __s_add_attr(e, "cn", ptr->name);
3316 if (rc != NS_LDAP_SUCCESS) {
3317 __s_cvt_freeEntryRdn(entry, rdn);
3318 return (rc);
3321 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
3322 if (rc != NS_LDAP_SUCCESS) {
3323 __s_cvt_freeEntryRdn(entry, rdn);
3324 return (rc);
3327 rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
3328 if (rc != NS_LDAP_SUCCESS) {
3329 __s_cvt_freeEntryRdn(entry, rdn);
3330 return (rc);
3333 rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
3334 if (rc != NS_LDAP_SUCCESS) {
3335 __s_cvt_freeEntryRdn(entry, rdn);
3336 return (rc);
3339 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3340 if (rc != NS_LDAP_SUCCESS) {
3341 __s_cvt_freeEntryRdn(entry, rdn);
3342 return (rc);
3345 if (ptr->res1 != NULL) {
3346 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
3347 if (rc != NS_LDAP_SUCCESS) {
3348 __s_cvt_freeEntryRdn(entry, rdn);
3349 return (rc);
3353 if (ptr->res2 != NULL) {
3354 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
3355 if (rc != NS_LDAP_SUCCESS) {
3356 __s_cvt_freeEntryRdn(entry, rdn);
3357 return (rc);
3361 return (NS_LDAP_SUCCESS);
3364 * Conversion: prof_attr
3365 * Input format: profstr_t
3366 * Exported objectclass: SolarisProfAttr
3368 static int
3369 __s_cvt_profattr(const void *data, char **rdn,
3370 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3372 ns_ldap_entry_t *e;
3373 int rc;
3374 char trdn[RDNSIZE];
3375 /* routine specific */
3376 profstr_t *ptr;
3377 int max_attr = 5;
3378 static char *oclist[] = {
3379 "SolarisProfAttr",
3380 "top",
3381 NULL
3384 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3385 return (NS_LDAP_OP_FAILED);
3387 *entry = e = __s_mk_entry(oclist, max_attr);
3388 if (e == NULL)
3389 return (NS_LDAP_MEMORY);
3391 /* Convert the structure */
3392 ptr = (profstr_t *)data;
3394 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3395 __ns_ldap_freeEntry(e);
3396 *entry = NULL;
3397 return (NS_LDAP_INVALID_PARAM);
3400 /* Create an appropriate rdn */
3401 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3402 *rdn = strdup(trdn);
3403 if (*rdn == NULL) {
3404 __ns_ldap_freeEntry(e);
3405 *entry = NULL;
3406 return (NS_LDAP_MEMORY);
3409 rc = __s_add_attr(e, "cn", ptr->name);
3410 if (rc != NS_LDAP_SUCCESS) {
3411 __s_cvt_freeEntryRdn(entry, rdn);
3412 return (rc);
3415 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3416 if (rc != NS_LDAP_SUCCESS) {
3417 __s_cvt_freeEntryRdn(entry, rdn);
3418 return (rc);
3421 if (ptr->res1 != NULL) {
3422 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3423 if (rc != NS_LDAP_SUCCESS) {
3424 __s_cvt_freeEntryRdn(entry, rdn);
3425 return (rc);
3429 if (ptr->res2 != NULL) {
3430 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3431 if (rc != NS_LDAP_SUCCESS) {
3432 __s_cvt_freeEntryRdn(entry, rdn);
3433 return (rc);
3437 if (ptr->desc != NULL) {
3438 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3439 if (rc != NS_LDAP_SUCCESS) {
3440 __s_cvt_freeEntryRdn(entry, rdn);
3441 return (rc);
3445 return (NS_LDAP_SUCCESS);
3448 * Conversion: user_attr
3449 * Input format: userstr_t
3450 * Exported objectclass: SolarisUserAttr
3452 static int
3453 __s_cvt_userattr(const void *data, char **rdn,
3454 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3456 ns_ldap_entry_t *e;
3457 int rc;
3458 char trdn[RDNSIZE];
3459 /* routine specific */
3460 userstr_t *ptr;
3461 int max_attr = 5;
3462 static char *oclist[] = {
3463 "SolarisUserAttr",
3464 NULL
3467 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3468 return (NS_LDAP_OP_FAILED);
3470 *entry = e = __s_mk_entry(oclist, max_attr);
3471 if (e == NULL)
3472 return (NS_LDAP_MEMORY);
3474 /* Convert the structure */
3475 ptr = (userstr_t *)data;
3477 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3478 ptr->attr == NULL) {
3479 __ns_ldap_freeEntry(e);
3480 *entry = NULL;
3481 return (NS_LDAP_INVALID_PARAM);
3484 /* Create an appropriate rdn */
3485 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3486 *rdn = strdup(trdn);
3487 if (*rdn == NULL) {
3488 __ns_ldap_freeEntry(e);
3489 *entry = NULL;
3490 return (NS_LDAP_MEMORY);
3494 * SolarisUserAttr has no uid attribute
3497 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3498 if (rc != NS_LDAP_SUCCESS) {
3499 __s_cvt_freeEntryRdn(entry, rdn);
3500 return (rc);
3503 if (ptr->qualifier != NULL) {
3504 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3505 if (rc != NS_LDAP_SUCCESS) {
3506 __s_cvt_freeEntryRdn(entry, rdn);
3507 return (rc);
3511 if (ptr->res1 != NULL) {
3512 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3513 if (rc != NS_LDAP_SUCCESS) {
3514 __s_cvt_freeEntryRdn(entry, rdn);
3515 return (rc);
3519 if (ptr->res2 != NULL) {
3520 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3521 if (rc != NS_LDAP_SUCCESS) {
3522 __s_cvt_freeEntryRdn(entry, rdn);
3523 return (rc);
3527 return (NS_LDAP_SUCCESS);
3530 * Add Typed Entry Conversion data structures
3533 typedef struct __ns_cvt_type {
3534 const char *service;
3535 int flags;
3536 #define AE 1 /* alway add entries */
3537 int (*cvt_rtn)(const void *data,
3538 char **rdn,
3539 ns_ldap_entry_t **entry,
3540 ns_ldap_error_t **errorp);
3541 } __ns_cvt_type_t;
3543 static __ns_cvt_type_t __s_cvtlist[] = {
3544 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd },
3545 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group },
3546 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts },
3547 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts },
3548 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc },
3549 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols },
3550 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks },
3551 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups },
3552 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases },
3553 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services },
3554 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers },
3555 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow },
3556 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks },
3557 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams },
3558 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr },
3559 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr },
3560 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr },
3561 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr },
3562 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
3563 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
3564 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project },
3565 { NULL, 0, NULL },
3569 * Add Typed Entry Routine
3572 /*ARGSUSED*/
3573 int __ns_ldap_addTypedEntry(
3574 const char *servicetype,
3575 const char *basedn,
3576 const void *data,
3577 const int create,
3578 const ns_cred_t *cred,
3579 const int flags,
3580 ns_ldap_error_t **errorp)
3582 char *rdn = NULL, *fulldn = NULL;
3583 void **paramVal = NULL;
3584 ns_ldap_entry_t *entry = NULL;
3585 const ns_ldap_attr_t *const *modattrlist;
3586 ns_ldap_search_desc_t **sdlist;
3587 char **dns = NULL;
3588 char trdn[RDNSIZE];
3589 char service[BUFSIZE];
3590 int rc = 0;
3591 int automount = 0;
3592 int i, s;
3594 rc = NS_LDAP_OP_FAILED;
3595 for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3596 if (__s_cvtlist[s].cvt_rtn == NULL)
3597 continue;
3598 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3599 break;
3600 /* Or, check if the servicetype is auto_ */
3601 if (strcmp(__s_cvtlist[s].service,
3602 NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3603 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3604 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3605 automount++;
3606 break;
3609 if (__s_cvtlist[s].service == NULL)
3610 return (rc);
3612 /* Convert the data */
3613 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3614 if (rc != NS_LDAP_SUCCESS) {
3615 __s_cvt_freeEntryRdn(&entry, &rdn);
3616 return (rc);
3618 if (rdn == NULL) {
3619 __ns_ldap_freeEntry(entry);
3620 return (NS_LDAP_OP_FAILED);
3623 if (strcmp(servicetype, "publickey") == 0) {
3624 struct _ns_pubkey *ptr;
3625 ptr = (struct _ns_pubkey *)data;
3626 if (ptr->hostcred == NS_HOSTCRED_TRUE)
3627 (void) strcpy(service, "hosts");
3628 else
3629 (void) strcpy(service, "passwd");
3630 } else
3631 (void) strcpy(service, servicetype);
3633 /* Create the Full DN */
3634 if (basedn == NULL) {
3635 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3636 &sdlist, errorp);
3637 if (rc != NS_LDAP_SUCCESS) {
3638 __s_cvt_freeEntryRdn(&entry, &rdn);
3639 return (rc);
3642 if (sdlist == NULL) {
3643 rc = __s_api_getDNs(&dns, service, errorp);
3644 if (rc != NS_LDAP_SUCCESS) {
3645 if (dns) {
3646 __s_api_free2dArray(dns);
3647 dns = NULL;
3649 __s_cvt_freeEntryRdn(&entry, &rdn);
3650 return (rc);
3652 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3653 __s_api_free2dArray(dns);
3654 } else {
3655 if (sdlist[0]->basedn) {
3656 (void) snprintf(trdn, RDNSIZE, "%s,%s",
3657 rdn, sdlist[0]->basedn);
3658 } else {
3659 __s_cvt_freeEntryRdn(&entry, &rdn);
3660 return (NS_LDAP_OP_FAILED);
3663 i = strlen(trdn) - 1;
3664 if (trdn[i] == COMMATOK) {
3665 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3666 &paramVal, errorp);
3667 if (rc != NS_LDAP_SUCCESS) {
3668 __s_cvt_freeEntryRdn(&entry, &rdn);
3669 return (rc);
3671 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3672 fulldn = (char *)calloc(i, 1);
3673 if (fulldn == NULL) {
3674 (void) __ns_ldap_freeParam(&paramVal);
3675 __s_cvt_freeEntryRdn(&entry, &rdn);
3676 return (NS_LDAP_MEMORY);
3678 (void) snprintf(fulldn, i, "%s%s", trdn,
3679 (char *)(paramVal[0]));
3680 (void) __ns_ldap_freeParam(&paramVal);
3681 } else {
3682 fulldn = strdup(trdn);
3683 if (fulldn == NULL) {
3684 __s_cvt_freeEntryRdn(&entry, &rdn);
3685 return (NS_LDAP_MEMORY);
3688 } else {
3689 i = strlen(rdn) + strlen(basedn) + 2;
3690 fulldn = (char *)calloc(i, 1);
3691 if (fulldn == NULL) {
3692 __s_cvt_freeEntryRdn(&entry, &rdn);
3693 return (NS_LDAP_MEMORY);
3695 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3698 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3699 /* Check to see if the entry exists already */
3700 /* May need to delete or update first */
3702 if (create != 1) {
3703 /* Modify the entry */
3705 * To add a shadow-like entry, the addTypedEntry function
3706 * would call __ns_ldap_repAttr first, and if server says
3707 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
3708 * This is to allow a netmask entry to be added even if the
3709 * base network entry is not in the directory. It would work
3710 * because the difference between the schema for the network
3711 * and netmask data contains only MAY attributes.
3713 * But for shadow data, the attributes do not have MUST
3714 * attributes the base entry needs, so if the __ns_ldap_addEntry
3715 * is executed, it would fail. The real reason, however, is that
3716 * the base entry did not exist. So returning
3717 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
3719 if ((__s_cvtlist[s].flags & AE) != 0)
3720 rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3721 cred, flags, errorp);
3722 else {
3723 rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3724 cred, flags, errorp);
3725 if (rc == NS_LDAP_INTERNAL && *errorp &&
3726 (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3727 (void) __ns_ldap_freeError(errorp);
3728 rc = __ns_ldap_addEntry(service, fulldn,
3729 entry, cred, flags, errorp);
3730 if (rc == NS_LDAP_INTERNAL && *errorp &&
3731 (*errorp)->status ==
3732 LDAP_OBJECT_CLASS_VIOLATION)
3733 (*errorp)->status = LDAP_NO_SUCH_OBJECT;
3736 } else {
3737 /* Add the entry */
3738 rc = __ns_ldap_addEntry(service, fulldn, entry,
3739 cred, flags, errorp);
3740 if (rc == NS_LDAP_INTERNAL && *errorp &&
3741 (*errorp)->status == LDAP_ALREADY_EXISTS &&
3742 ((strcmp(service, "ethers") == 0) ||
3743 (strcmp(service, "bootparams") == 0))) {
3744 rc = modify_ethers_bootp(service, rdn, fulldn,
3745 modattrlist, cred, flags, errorp);
3749 /* Free up entry created by conversion routine */
3750 free(fulldn);
3751 __s_cvt_freeEntryRdn(&entry, &rdn);
3752 return (rc);
3757 * Append the default base dn to the dn
3758 * when it ends with ','.
3759 * e.g.
3760 * SSD = service:ou=foo,
3763 __s_api_append_default_basedn(const char *dn, char **new_dn, int *allocated,
3764 ns_ldap_error_t **errp)
3767 int rc = NS_LDAP_SUCCESS, len = 0;
3768 void **param = NULL;
3769 char *str = NULL;
3771 *allocated = FALSE;
3772 *new_dn = NULL;
3774 if (dn == NULL)
3775 return (NS_LDAP_INVALID_PARAM);
3777 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3778 (void ***)&param, errp);
3780 if (rc != NS_LDAP_SUCCESS) {
3781 if (param)
3782 (void) __ns_ldap_freeParam(&param);
3783 return (rc);
3786 len = strlen(dn);
3787 str = ((char **)param)[0];
3788 len = len + strlen(str) +1;
3789 *new_dn = (char *)malloc(len);
3790 if (*new_dn == NULL) {
3791 (void) __ns_ldap_freeParam(&param);
3792 return (NS_LDAP_MEMORY);
3794 *allocated = TRUE;
3796 (void) strcpy(*new_dn, dn);
3797 (void) strcat(*new_dn, str);
3799 (void) __ns_ldap_freeParam(&param);
3800 return (NS_LDAP_SUCCESS);
3804 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
3805 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
3806 * The output contains a count, a list of offsets, which show where the
3807 * corresponding copied attribute type and attribute value are located.
3808 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
3809 * the output is the ldap_strlist_t structure with: ldap_count = 6,
3810 * (buf + ldap_offsets[0]) -> "dn"
3811 * (buf + ldap_offsets[1]) -> "aaaa"
3812 * (buf + ldap_offsets[2]) -> "userPassword"
3813 * (buf + ldap_offsets[3]) -> "bbbb"
3814 * (buf + ldap_offsets[4]) -> "shadowlastchange"
3815 * (buf + ldap_offsets[5]) -> "cccc"
3816 * and all the string data shown above copied into the buffer after
3817 * the offset array. The total length of the data will be the return
3818 * value, or -1 if error.
3820 static int
3821 attr2list(const char *dn, ns_ldap_attr_t **attr,
3822 char *buf, int bufsize)
3824 int c = 0;
3825 char *ap;
3826 int ao;
3827 ldap_strlist_t *al = (ldap_strlist_t *)buf;
3828 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
3829 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
3831 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
3832 if ((strlen(dn) + 2 + 1) >= bufsize)
3833 return (-1);
3835 /* count number of attributes */
3836 while (*aptr++)
3837 c++;
3838 al->ldap_count = 2 + c * 2;
3839 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
3840 al->ldap_count;
3841 if (ao > bufsize)
3842 return (-1);
3843 al->ldap_offsets[0] = ao;
3844 ap = buf + ao;
3845 ao += 3;
3847 /* copy entry DN */
3848 if (ao > bufsize)
3849 return (-1);
3850 (void) strlcpy(ap, "dn", bufsize);
3851 ap += 3;
3853 al->ldap_offsets[1] = ao;
3854 ao += strlen(dn) + 1;
3855 if (ao > bufsize)
3856 return (-1);
3857 (void) strlcpy(ap, dn, bufsize);
3858 ap = buf + ao;
3860 aptr = attr;
3861 for (c = 2; c < al->ldap_count; c++, aptr++) {
3862 a = *aptr;
3863 if (a->attrname == NULL || a->attrvalue == NULL ||
3864 a->value_count != 1 || a->attrvalue[0] == NULL)
3865 return (-1);
3866 al->ldap_offsets[c] = ao;
3867 ao += strlen(a->attrname) + 1;
3868 if (ao > bufsize)
3869 return (-1);
3870 (void) strlcpy(ap, a->attrname, bufsize);
3871 ap = buf + ao;
3873 c++;
3874 al->ldap_offsets[c] = ao;
3875 ao += strlen(a->attrvalue[0]) + 1;
3876 (void) strlcpy(ap, a->attrvalue[0], bufsize);
3877 ap = buf + ao;
3880 return (ao);
3884 * Send a modify request to the ldap_cachemgr daemon
3885 * which will use the admin credential to perform the
3886 * operation.
3889 static int
3890 send_to_cachemgr(
3891 const char *dn,
3892 ns_ldap_attr_t **attr,
3893 ns_ldap_error_t **errorp)
3895 union {
3896 ldap_data_t s_d;
3897 char s_b[DOORBUFFERSIZE];
3898 } space;
3900 ldap_data_t *sptr;
3901 int ndata;
3902 int adata;
3903 int len;
3904 int rc;
3905 char errstr[MAXERROR];
3906 ldap_admin_mod_result_t *admin_result;
3908 *errorp = NULL;
3909 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
3910 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
3911 sizeof (space) - offsetof(ldap_return_t, ldap_u));
3912 if (len <= 0)
3913 return (NS_LDAP_INVALID_PARAM);
3915 adata = sizeof (ldap_call_t) + len;
3916 ndata = sizeof (space);
3917 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
3918 sptr = &space.s_d;
3920 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
3921 case NS_CACHE_SUCCESS:
3922 break;
3923 case NS_CACHE_NOTFOUND:
3924 (void) snprintf(errstr, sizeof (errstr),
3925 gettext("Door call ADMINMODIFY to "
3926 "ldap_cachemgr failed - error: %d"),
3927 space.s_d.ldap_ret.ldap_errno);
3928 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
3929 strdup(errstr), 0);
3930 return (NS_LDAP_OP_FAILED);
3931 default:
3932 return (NS_LDAP_OP_FAILED);
3935 admin_result = &sptr->ldap_ret.ldap_u.admin_result;
3936 if (admin_result->ns_err == NS_LDAP_SUCCESS)
3937 rc = NS_LDAP_SUCCESS;
3938 else {
3939 rc = admin_result->ns_err;
3940 if (admin_result->msg_size == 0)
3941 *errorp = __s_api_make_error(admin_result->status,
3942 NULL);
3943 else
3944 *errorp = __s_api_make_error(admin_result->status,
3945 admin_result->msg);
3948 /* clean up the door call */
3949 if (sptr != &space.s_d) {
3950 (void) munmap((char *)sptr, ndata);
3953 return (rc);