1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <libintl.h>
30
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <strings.h>
36 #include <lber.h>
37 #include <ldap.h>
38 #include <syslog.h>
39 #include <stddef.h>
40 #include <sys/mman.h>
41
42 #include "ns_sldap.h"
43 #include "ns_internal.h"
44 #include "ns_connmgmt.h"
45 #include "ns_cache_door.h"
46
47 /* Additional headers for addTypedEntry Conversion routines */
48 #include <pwd.h>
49 #include <project.h>
50 #include <shadow.h>
51 #include <grp.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54 #include <netdb.h>
55 #include <rpc/rpcent.h>
56 #include <auth_attr.h>
57 #include <exec_attr.h>
58 #include <prof_attr.h>
59 #include <user_attr.h>
60 #include <bsm/libbsm.h>
61 #include <sys/tsol/tndb.h>
62 #include <tsol/label.h>
63
64 static int send_to_cachemgr(const char *,
65 ns_ldap_attr_t **, ns_ldap_error_t **);
66
67 static int escape_str(char *, char *);
68
69 /*
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
80 *
81 */
82 static int
replace_mapped_attr_in_dn(const char * service,const char * dn,char ** new_dn)83 replace_mapped_attr_in_dn(
84 const char *service, const char *dn, char **new_dn)
85 {
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;
92
93 *new_dn = NULL;
94
95 /*
96 * separate dn into individual componets
97 * e.g.
98 * "automountKey=user_01" , "automountMapName_test=auto_home", ...
99 */
100 dnArray = ldap_explode_dn(dn, 0);
101 if (!dnArray || !*dnArray)
102 return (NS_LDAP_INVALID_PARAM);
103
104 cur = strchr(dnArray[0], '=');
105 if (!cur) {
106 __s_api_free2dArray(dnArray);
107 return (NS_LDAP_INVALID_PARAM);
108 }
109 *cur = '\0';
110
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;
117
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);
124 }
125 orig_len = strlen(dnArray[0]);
126
127 /*
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
134 */
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);
143 }
144
145 (void) snprintf(*new_dn, len, "%s=%s", mappedattr[0], dn + orig_len +1);
146 __s_api_free2dArray(dnArray);
147 __s_api_free2dArray(mappedattr);
148
149 return (NS_LDAP_SUCCESS);
150 }
151
152
153 /*
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.
157 */
158 static int
init_bval_mod(LDAPMod * mod,int mop,char * mtype,char * mvptr,int mvlen)159 init_bval_mod(
160 LDAPMod *mod,
161 int mop,
162 char *mtype,
163 char *mvptr,
164 int mvlen)
165 {
166
167 struct berval **bmodval;
168
169 /* dup attribute name */
170 mod->mod_type = strdup(mtype);
171 if (mod->mod_type == NULL)
172 return (-1);
173
174 /*
175 * assume single value,
176 * since only one value/length pair passed in
177 */
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);
183 }
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);
190 }
191
192 /* set pointer to data */
193 bmodval[0]->bv_val = mvptr;
194
195 /* set length */
196 bmodval[0]->bv_len = mvlen;
197
198 /*
199 * turn on the BVALUE bit to indicate
200 * that the length of data is supplied
201 */
202 mod->mod_op = mop | LDAP_MOD_BVALUES;
203
204 mod->mod_bvalues = bmodval;
205
206 return (0);
207 }
208
209 static void
freeModList(LDAPMod ** mods)210 freeModList(LDAPMod **mods)
211 {
212 int i, j;
213 int name_is_oc;
214
215 if (mods == NULL)
216 return;
217
218 for (i = 0; mods[i]; i++) {
219
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);
226 }
227
228 if (mods[i]->mod_bvalues == NULL)
229 continue;
230 /*
231 * LDAP_MOD_BVALUES is only set by
232 * the "gecos" 1 to N attribute mapping
233 * code, and the attribute is single valued.
234 */
235 if (mods[i]->mod_op & LDAP_MOD_BVALUES) {
236 if (mods[i]->mod_bvalues[0])
237 free(mods[i]->mod_bvalues[0]);
238 } else {
239 if (name_is_oc) {
240 /*
241 * only values for the "objectclass"
242 * were dupped using strdup.
243 * other attribute values were
244 * not dupped, but via pointer
245 * assignment. So here the
246 * values for "objectclass"
247 * is freed one by one,
248 * but the values for other
249 * attributes need not be freed.
250 */
251 for (j = 0; mods[i]->mod_values[j]; j++)
252 free(mods[i]->mod_values[j]);
253 }
254
255 }
256 free(mods[i]->mod_bvalues);
257 }
258
259 /* modlist */
260 free((char *)(mods[0]));
261 free(mods);
262 }
263
264 static LDAPMod **
__s_api_makeModListCount(const char * service,const ns_ldap_attr_t * const * attr,const int mod_op,const int count,const int flags)265 __s_api_makeModListCount(
266 const char *service,
267 const ns_ldap_attr_t * const *attr,
268 const int mod_op,
269 const int count,
270 const int flags)
271 {
272 LDAPMod **mods, *modlist;
273 char **modval;
274 char **mapping;
275 int i;
276 int j;
277 int k, rc, vlen;
278 char *c, *comma1 = NULL, *comma2 = NULL;
279 int schema_mapping_existed = FALSE;
280 int auto_service = FALSE;
281
282
283 /*
284 * add 2 for "gecos" 1 to up to 3 attribute mapping
285 */
286 mods = (LDAPMod **)calloc((count + 3), sizeof (LDAPMod *));
287 if (mods == NULL) {
288 return (NULL);
289 }
290 /*
291 * add 2 for "gecos" 1 to up to 3 attribute mapping
292 */
293 modlist = (LDAPMod *)calloc(count + 2, sizeof (LDAPMod));
294 if (modlist == NULL) {
295 free(mods);
296 return (NULL);
297 }
298
299 if (service != NULL && strncasecmp(service, NS_LDAP_TYPE_AUTOMOUNT,
300 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
301 auto_service = TRUE;
302
303 /*
304 * see if schema mapping existed for the given service
305 */
306 mapping = __ns_ldap_getOrigAttribute(service,
307 NS_HASH_SCHEMA_MAPPING_EXISTED);
308 if (mapping) {
309 schema_mapping_existed = TRUE;
310 __s_api_free2dArray(mapping);
311 mapping = NULL;
312 }
313
314 for (i = 0, k = 0; k < count && attr[k] != NULL; i++, k++) {
315 mods[i] = &modlist[i];
316 mods[i]->mod_op = mod_op;
317 /*
318 * Perform attribute mapping if necessary.
319 */
320 if (schema_mapping_existed && (flags & NS_LDAP_NOMAP) == 0) {
321 mapping = __ns_ldap_getMappedAttributes(service,
322 attr[k]->attrname);
323 } else
324 mapping = NULL;
325
326 if (mapping == NULL && auto_service &&
327 (flags & NS_LDAP_NOMAP) == 0) {
328 /*
329 * if service == auto_xxx and
330 * no mapped attribute is found
331 * and NS_LDAP_NOMAP is not set
332 * then try automount's mapped attribute
333 */
334 mapping = __ns_ldap_getMappedAttributes("automount",
335 attr[k]->attrname);
336 }
337
338 if (mapping == NULL) {
339 mods[i]->mod_type = strdup(attr[k]->attrname);
340 if (mods[i]->mod_type == NULL)
341 goto free_memory;
342 } else {
343 /*
344 * 1 to N attribute mapping is only done for "gecos",
345 * and only 1 to 3 mapping.
346 * nine cases here:
347 *
348 * A. attrMap=passwd:gecos=a
349 * 1. gecos="xx,yy,zz" -> a="xx,yy,zz"
350 * 2. gecos="xx,yy" -> a="xx,yy"
351 * 3. gecos="xx" -> a="xx"
352 *
353 * B. attrMap=passwd:gecos=a b
354 * 4. gecos="xx,yy,zz" -> a="xx" b="yy,zz"
355 * 5. gecos="xx,yy" -> a="xx" b="yy"
356 * 6. gecos="xx" -> a="xx"
357 *
358 * C. attrMap=passwd:gecos=a b c
359 * 7. gecos="xx,yy,zz" -> a="xx" b="yy" c="zz"
360 * 8. gecos="xx,yy" -> a="xx" b="yy"
361 * 9. gecos="xx" -> a="xx"
362 *
363 * This can be grouped as:
364 *
365 * c1 cases: 1,2,3,6,9
366 * if ((attrMap=passwd:gecos=a) ||
367 * (no "," in gecos value))
368 * same as other no-mapping attributes,
369 * no special processing needed
370 * else
371 *
372 * c2 cases: 4,5,8
373 * if ((attrMap=passwd:gecos=a b) ||
374 * (only one "," in gecos value))
375 * a=xx b=yy[,...]
376 * else
377 *
378 * c3 case: 7
379 * a=xx b=yy c=...
380 *
381 * notes: in case c2 and c3, ... could still contain ","
382 */
383 if (strcasecmp(service, "passwd") == 0 &&
384 strcasecmp(attr[k]->attrname, "gecos") == 0 &&
385 mapping[1] && attr[k]->attrvalue[0] &&
386 (comma1 = strchr(attr[k]->attrvalue[0],
387 COMMATOK)) != NULL) {
388
389 /* is there a second comma? */
390 if (*(comma1 + 1) != '\0')
391 comma2 = strchr(comma1 + 1, COMMATOK);
392
393 /*
394 * Process case c2 or c3.
395 * case c2: mapped to two attributes or just
396 * one comma
397 */
398 if (mapping[2] == NULL || comma2 == NULL) {
399 /* case c2 */
400
401 /*
402 * int mod structure for the first attribute
403 */
404 vlen = comma1 - attr[k]->attrvalue[0];
405 c = attr[k]->attrvalue[0];
406
407 if (vlen > 0 && c) {
408 rc = init_bval_mod(mods[i], mod_op,
409 mapping[0], c, vlen);
410 if (rc != 0)
411 goto free_memory;
412 } else {
413 /* don't leave a hole in mods array */
414 mods[i] = NULL;
415 i--;
416 }
417
418
419 /*
420 * init mod structure for the 2nd attribute
421 */
422 if (*(comma1 + 1) == '\0') {
423 __s_api_free2dArray(mapping);
424 mapping = NULL;
425 continue;
426 }
427
428 i++;
429 mods[i] = &modlist[i];
430
431 /*
432 * get pointer to data.
433 * Skip leading spaces.
434 */
435 for (c = comma1 + 1; *c == SPACETOK; c++) {
436 /* empty */
437 }
438
439 /* get data length */
440 vlen = strlen(attr[k]->attrvalue[0]) -
441 (c - attr[k]->attrvalue[0]);
442
443 if (vlen > 0 && c) {
444 rc = init_bval_mod(mods[i], mod_op,
445 mapping[1], c, vlen);
446 if (rc != 0)
447 goto free_memory;
448 } else {
449 /* don't leave a hole in mods array */
450 mods[i] = NULL;
451 i--;
452 }
453
454 /* done with the mapping array */
455 __s_api_free2dArray(mapping);
456 mapping = NULL;
457
458 continue;
459 } else {
460 /* case c3 */
461
462 /*
463 * int mod structure for the first attribute
464 */
465 vlen = comma1 - attr[k]->attrvalue[0];
466 c = attr[k]->attrvalue[0];
467
468 if (vlen > 0 && c) {
469 rc = init_bval_mod(mods[i], mod_op,
470 mapping[0], c, vlen);
471 if (rc != 0)
472 goto free_memory;
473 } else {
474 /* don't leave a hole in mods array */
475 mods[i] = NULL;
476 i--;
477 }
478
479 /*
480 * init mod structure for the 2nd attribute
481 */
482 i++;
483 mods[i] = &modlist[i];
484
485 /*
486 * get pointer to data.
487 * Skip leading spaces.
488 */
489 for (c = comma1 + 1; *c == SPACETOK; c++) {
490 /* empty */
491 };
492
493 /* get data length */
494 vlen = comma2 - c;
495
496 if (vlen > 0 && c) {
497 rc = init_bval_mod(mods[i], mod_op,
498 mapping[1], c, vlen);
499 if (rc != 0)
500 goto free_memory;
501 } else {
502 /* don't leave a hole in mods array */
503 mods[i] = NULL;
504 i--;
505 }
506
507 /*
508 * init mod structure for the 3rd attribute
509 */
510 if (*(comma2 + 1) == '\0') {
511 __s_api_free2dArray(mapping);
512 mapping = NULL;
513 continue;
514 }
515
516 i++;
517 mods[i] = &modlist[i];
518 /*
519 * get pointer to data.
520 * Skip leading spaces.
521 */
522 for (c = comma2 + 1; *c == SPACETOK; c++) {
523 /* empty */
524 }
525
526 /* get data length */
527 vlen = strlen(attr[k]->attrvalue[0]) -
528 (c - attr[k]->attrvalue[0]);
529
530 if (vlen > 0 && c) {
531 rc = init_bval_mod(mods[i], mod_op,
532 mapping[2], c, vlen);
533 if (rc != 0)
534 goto free_memory;
535 } else {
536 /* don't leave a hole in mods array */
537 mods[i] = NULL;
538 i--;
539 }
540
541 /* done with the mapping array */
542 __s_api_free2dArray(mapping);
543 mapping = NULL;
544
545 continue;
546 }
547 }
548
549 /* case c1 */
550 mods[i]->mod_type = strdup(mapping[0]);
551 if (mods[i]->mod_type == NULL) {
552 goto free_memory;
553 }
554 __s_api_free2dArray(mapping);
555 mapping = NULL;
556 }
557
558 modval = (char **)calloc(attr[k]->value_count+1,
559 sizeof (char *));
560 if (modval == NULL)
561 goto free_memory;
562 /*
563 * Perform objectclass mapping.
564 * Note that the values for the "objectclass" attribute
565 * will be dupped using strdup. Values for other
566 * attributes will be referenced via pointer
567 * assignments.
568 */
569 if (strcasecmp(mods[i]->mod_type, "objectclass") == 0) {
570 for (j = 0; j < attr[k]->value_count; j++) {
571 if (schema_mapping_existed &&
572 (flags & NS_LDAP_NOMAP) == 0)
573 mapping =
574 __ns_ldap_getMappedObjectClass(
575 service, attr[k]->attrvalue[j]);
576 else
577 mapping = NULL;
578
579 if (mapping == NULL && auto_service &&
580 (flags & NS_LDAP_NOMAP) == 0)
581 /*
582 * if service == auto_xxx and
583 * no mapped objectclass is found
584 * then try automount
585 */
586 mapping =
587 __ns_ldap_getMappedObjectClass(
588 "automount", attr[k]->attrvalue[j]);
589
590 if (mapping && mapping[0]) {
591 /* assume single mapping */
592 modval[j] = strdup(mapping[0]);
593 } else {
594 modval[j] = strdup(attr[k]->
595 attrvalue[j]);
596 }
597 if (modval[j] == NULL)
598 goto free_memory;
599 }
600 } else {
601 for (j = 0; j < attr[k]->value_count; j++) {
602 /* ASSIGN NOT COPY */
603 modval[j] = attr[k]->attrvalue[j];
604 }
605 }
606 mods[i]->mod_values = modval;
607 }
608
609 return (mods);
610
611 free_memory:
612 freeModList(mods);
613 if (mapping)
614 __s_api_free2dArray(mapping);
615
616 return (NULL);
617
618 }
619
620 static LDAPMod **
__s_api_makeModList(const char * service,const ns_ldap_attr_t * const * attr,const int mod_op,const int flags)621 __s_api_makeModList(
622 const char *service,
623 const ns_ldap_attr_t * const *attr,
624 const int mod_op,
625 const int flags)
626 {
627 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
628 int count = 0;
629
630 if (aptr == NULL)
631 return (NULL);
632
633 /* count number of attributes */
634 while (*aptr++)
635 count++;
636
637 return (__s_api_makeModListCount(service, attr, mod_op, count, flags));
638 }
639
640 static void
__s_cvt_freeEntryRdn(ns_ldap_entry_t ** entry,char ** rdn)641 __s_cvt_freeEntryRdn(ns_ldap_entry_t **entry, char **rdn)
642 {
643 if (*entry != NULL) {
644 __ns_ldap_freeEntry(*entry);
645 *entry = NULL;
646 }
647 if (*rdn != NULL) {
648 free(*rdn);
649 *rdn = NULL;
650 }
651 }
652
653 /*
654 * This state machine performs one or more LDAP add/delete/modify
655 * operations to configured LDAP servers.
656 */
657 static int
write_state_machine(int ldap_op,char * dn,LDAPMod ** mods,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)658 write_state_machine(
659 int ldap_op,
660 char *dn,
661 LDAPMod **mods,
662 const ns_cred_t *cred,
663 const int flags,
664 ns_ldap_error_t ** errorp)
665 {
666 ConnectionID connectionId = -1;
667 Connection *conp = NULL;
668 LDAPMessage *res;
669 char *target_dn = NULL;
670 char errstr[MAXERROR];
671 int rc = NS_LDAP_SUCCESS;
672 int return_rc = NS_LDAP_SUCCESS;
673 int followRef = FALSE;
674 int target_dn_allocated = FALSE;
675 int len;
676 int msgid;
677 int Errno;
678 boolean_t from_get_lderrno = B_FALSE;
679 int always = 1;
680 char *err, *errmsg = NULL;
681 /* referrals returned by the LDAP operation */
682 char **referrals = NULL;
683 /*
684 * list of referrals used by the state machine, built from
685 * the referrals variable above
686 */
687 ns_referral_info_t *ref_list = NULL;
688 /* current referral */
689 ns_referral_info_t *current_ref = NULL;
690 ns_write_state_t state = W_INIT, new_state, err_state = W_INIT;
691 int do_not_fail_if_new_pwd_reqd = 0;
692 ns_ldap_passwd_status_t pwd_status = NS_PASSWD_GOOD;
693 int passwd_mgmt = 0;
694 int i = 0;
695 int ldap_error;
696 int nopasswd_acct_mgmt = 0;
697 ns_conn_user_t *conn_user = NULL;
698
699 while (always) {
700 switch (state) {
701 case W_EXIT:
702 /* return the MT connection and free the conn user */
703 if (conn_user != NULL) {
704 if (conn_user->use_mt_conn == B_TRUE) {
705 if (conn_user->ns_error != NULL) {
706 *errorp = conn_user->ns_error;
707 conn_user->ns_error = NULL;
708 return_rc = conn_user->ns_rc;
709 }
710 if (conn_user->conn_mt != NULL)
711 __s_api_conn_mt_return(
712 conn_user);
713 }
714 __s_api_conn_user_free(conn_user);
715 }
716
717 if (connectionId > -1)
718 DropConnection(connectionId, NS_LDAP_NEW_CONN);
719 if (ref_list)
720 __s_api_deleteRefInfo(ref_list);
721 if (target_dn && target_dn_allocated)
722 free(target_dn);
723 return (return_rc);
724 case W_INIT:
725 /* see if need to follow referrals */
726 rc = __s_api_toFollowReferrals(flags,
727 &followRef, errorp);
728 if (rc != NS_LDAP_SUCCESS) {
729 return_rc = rc;
730 new_state = W_ERROR;
731 break;
732 }
733 len = strlen(dn);
734 if (dn[len-1] == COMMATOK)
735 rc = __s_api_append_default_basedn(
736 dn, &target_dn, &target_dn_allocated,
737 errorp);
738 else
739 target_dn = dn;
740 if (rc != NS_LDAP_SUCCESS) {
741 return_rc = rc;
742 new_state = W_ERROR;
743 }
744 else
745 new_state = GET_CONNECTION;
746 break;
747 case GET_CONNECTION:
748 /* identify self as a write user */
749 conn_user = __s_api_conn_user_init(NS_CONN_USER_WRITE,
750 NULL, B_FALSE);
751 rc = __s_api_getConnection(NULL,
752 flags, cred, &connectionId, &conp, errorp,
753 do_not_fail_if_new_pwd_reqd, nopasswd_acct_mgmt,
754 conn_user);
755
756 /*
757 * If password control attached
758 * in *errorp,
759 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
760 * free the error structure (we do not need
761 * the password management info).
762 * Reset rc to NS_LDAP_SUCCESS.
763 */
764 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
765 (void) __ns_ldap_freeError(errorp);
766 *errorp = NULL;
767 rc = NS_LDAP_SUCCESS;
768 }
769
770 if (rc != NS_LDAP_SUCCESS) {
771 return_rc = rc;
772 new_state = W_ERROR;
773 break;
774 }
775 if (followRef)
776 new_state = SELECT_OPERATION_ASYNC;
777 else
778 new_state = SELECT_OPERATION_SYNC;
779 break;
780 case SELECT_OPERATION_SYNC:
781 if (ldap_op == LDAP_REQ_ADD)
782 new_state = DO_ADD_SYNC;
783 else if (ldap_op == LDAP_REQ_DELETE)
784 new_state = DO_DELETE_SYNC;
785 else if (ldap_op == LDAP_REQ_MODIFY)
786 new_state = DO_MODIFY_SYNC;
787 break;
788 case SELECT_OPERATION_ASYNC:
789 if (ldap_op == LDAP_REQ_ADD)
790 new_state = DO_ADD_ASYNC;
791 else if (ldap_op == LDAP_REQ_DELETE)
792 new_state = DO_DELETE_ASYNC;
793 else if (ldap_op == LDAP_REQ_MODIFY)
794 new_state = DO_MODIFY_ASYNC;
795 break;
796 case DO_ADD_SYNC:
797 rc = ldap_add_ext_s(conp->ld, target_dn,
798 mods, NULL, NULL);
799 new_state = GET_RESULT_SYNC;
800 break;
801 case DO_DELETE_SYNC:
802 rc = ldap_delete_ext_s(conp->ld, target_dn,
803 NULL, NULL);
804 new_state = GET_RESULT_SYNC;
805 break;
806 case DO_MODIFY_SYNC:
807 rc = ldap_modify_ext_s(conp->ld, target_dn,
808 mods, NULL, NULL);
809 new_state = GET_RESULT_SYNC;
810 break;
811 case DO_ADD_ASYNC:
812 rc = ldap_add_ext(conp->ld, target_dn,
813 mods, NULL, NULL, &msgid);
814 new_state = GET_RESULT_ASYNC;
815 break;
816 case DO_DELETE_ASYNC:
817 rc = ldap_delete_ext(conp->ld, target_dn,
818 NULL, NULL, &msgid);
819 new_state = GET_RESULT_ASYNC;
820 break;
821 case DO_MODIFY_ASYNC:
822 rc = ldap_modify_ext(conp->ld, target_dn,
823 mods, NULL, NULL, &msgid);
824 new_state = GET_RESULT_ASYNC;
825 break;
826 case GET_RESULT_SYNC:
827 if (rc != LDAP_SUCCESS) {
828 Errno = rc;
829 (void) ldap_get_lderrno(conp->ld,
830 NULL, &errmsg);
831
832 /*
833 * No need to deal with the error message if
834 * it's an empty string.
835 */
836 if (errmsg != NULL && *errmsg == '\0')
837 errmsg = NULL;
838
839 if (errmsg != NULL) {
840 /*
841 * ldap_get_lderrno does not expect
842 * errmsg to be freed after use, while
843 * ldap_parse_result below does, so set
844 * a flag to indicate source.
845 */
846 from_get_lderrno = B_TRUE;
847 }
848
849 new_state = W_LDAP_ERROR;
850 } else {
851 return_rc = NS_LDAP_SUCCESS;
852 new_state = W_EXIT;
853 }
854 break;
855 case GET_RESULT_ASYNC:
856 rc = ldap_result(conp->ld, msgid, 1,
857 (struct timeval *)NULL, &res);
858 /* if no server response, set Errno */
859 if (rc == -1) {
860 (void) ldap_get_option(conp->ld,
861 LDAP_OPT_ERROR_NUMBER, &Errno);
862 new_state = W_LDAP_ERROR;
863 break;
864 }
865 if (rc == LDAP_RES_ADD || rc == LDAP_RES_MODIFY ||
866 rc == LDAP_RES_DELETE) {
867 new_state = PARSE_RESULT;
868 break;
869 } else {
870 return_rc = rc;
871 new_state = W_ERROR;
872 }
873 break;
874 case PARSE_RESULT:
875 /*
876 * need Errno, referrals, error msg,
877 * and the last "1" is to free
878 * the result (res)
879 */
880 rc = ldap_parse_result(conp->ld, res, &Errno,
881 NULL, &errmsg, &referrals, NULL, 1);
882 /*
883 * free errmsg if it is an empty string
884 */
885 if (errmsg && *errmsg == '\0') {
886 ldap_memfree(errmsg);
887 errmsg = NULL;
888 }
889 /*
890 * If we received referral data, process
891 * it if:
892 * - we are configured to follow referrals
893 * - and not already in referral mode (to keep
894 * consistency with search_state_machine()
895 * which follows 1 level of referrals only;
896 * see proc_result_referrals() and
897 * proc_search_references().
898 */
899 if (Errno == LDAP_REFERRAL && followRef && !ref_list) {
900 for (i = 0; referrals[i] != NULL; i++) {
901 /* add to referral list */
902 rc = __s_api_addRefInfo(&ref_list,
903 referrals[i], NULL, NULL, NULL,
904 conp->ld);
905 if (rc != NS_LDAP_SUCCESS) {
906 __s_api_deleteRefInfo(ref_list);
907 ref_list = NULL;
908 break;
909 }
910 }
911 ldap_value_free(referrals);
912 if (ref_list == NULL) {
913 if (rc != NS_LDAP_MEMORY)
914 rc = NS_LDAP_INTERNAL;
915 return_rc = rc;
916 new_state = W_ERROR;
917 } else {
918 new_state = GET_REFERRAL_CONNECTION;
919 current_ref = ref_list;
920 }
921 if (errmsg) {
922 ldap_memfree(errmsg);
923 errmsg = NULL;
924 }
925 break;
926 }
927 if (Errno != LDAP_SUCCESS) {
928 new_state = W_LDAP_ERROR;
929 } else {
930 return_rc = NS_LDAP_SUCCESS;
931 new_state = W_EXIT;
932 }
933 break;
934 case GET_REFERRAL_CONNECTION:
935 /*
936 * since we are starting over,
937 * discard the old error info
938 */
939 return_rc = NS_LDAP_SUCCESS;
940 if (*errorp)
941 (void) __ns_ldap_freeError(errorp);
942 if (connectionId > -1)
943 DropConnection(connectionId, NS_LDAP_NEW_CONN);
944
945 /* set it up to use a referral connection */
946 if (conn_user != NULL) {
947 /*
948 * If an MT connection is being used,
949 * return it to the pool.
950 */
951 if (conn_user->conn_mt != NULL)
952 __s_api_conn_mt_return(conn_user);
953
954 conn_user->referral = B_TRUE;
955 }
956 rc = __s_api_getConnection(current_ref->refHost,
957 0, cred, &connectionId, &conp, errorp,
958 do_not_fail_if_new_pwd_reqd,
959 nopasswd_acct_mgmt, conn_user);
960
961 /*
962 * If password control attached
963 * in errorp,
964 * e.g. rc == NS_LDAP_SUCCESS_WITH_INFO,
965 * free the error structure (we do not need
966 * the password management info).
967 * Reset rc to NS_LDAP_SUCCESS.
968 */
969 if (rc == NS_LDAP_SUCCESS_WITH_INFO) {
970 (void) __ns_ldap_freeError(errorp);
971 *errorp = NULL;
972 rc = NS_LDAP_SUCCESS;
973 }
974
975 if (rc != NS_LDAP_SUCCESS) {
976 return_rc = rc;
977 /*
978 * If current referral is not
979 * available for some reason,
980 * try next referral in the list.
981 * Get LDAP error code from errorp.
982 */
983 if (*errorp != NULL) {
984 ns_write_state_t get_ref =
985 GET_REFERRAL_CONNECTION;
986
987 ldap_error = (*errorp)->status;
988 if (ldap_error == LDAP_BUSY ||
989 ldap_error == LDAP_UNAVAILABLE ||
990 ldap_error ==
991 LDAP_UNWILLING_TO_PERFORM ||
992 ldap_error == LDAP_CONNECT_ERROR ||
993 ldap_error == LDAP_SERVER_DOWN) {
994 current_ref = current_ref->next;
995 if (current_ref == NULL) {
996 /* no more referral to follow */
997 new_state = W_ERROR;
998 } else
999 new_state = get_ref;
1000 /*
1001 * free errorp before going to
1002 * next referral
1003 */
1004 (void) __ns_ldap_freeError(
1005 errorp);
1006 *errorp = NULL;
1007 break;
1008 }
1009 /*
1010 * free errorp before going to W_ERROR
1011 */
1012 (void) __ns_ldap_freeError(errorp);
1013 *errorp = NULL;
1014 }
1015 /* else, exit */
1016 __s_api_deleteRefInfo(ref_list);
1017 ref_list = NULL;
1018 new_state = W_ERROR;
1019 if (conn_user != NULL)
1020 conn_user->referral = B_FALSE;
1021 break;
1022 }
1023 /* target DN may changed due to referrals */
1024 if (current_ref->refDN) {
1025 if (target_dn && target_dn_allocated) {
1026 free(target_dn);
1027 target_dn = NULL;
1028 target_dn_allocated = FALSE;
1029 }
1030 target_dn = current_ref->refDN;
1031 }
1032 new_state = SELECT_OPERATION_SYNC;
1033 break;
1034 case W_LDAP_ERROR:
1035 /*
1036 * map error code and error message
1037 * to password status if necessary.
1038 * This is to see if password updates
1039 * failed due to password policy or
1040 * password syntax checking.
1041 */
1042 if (errmsg) {
1043 /*
1044 * check if server supports
1045 * password management
1046 */
1047 passwd_mgmt =
1048 __s_api_contain_passwd_control_oid(
1049 conp->controls);
1050 if (passwd_mgmt)
1051 pwd_status =
1052 __s_api_set_passwd_status(
1053 Errno, errmsg);
1054 /*
1055 * free only if not returned by ldap_get_lderrno
1056 */
1057 if (!from_get_lderrno)
1058 ldap_memfree(errmsg);
1059 errmsg = NULL;
1060 from_get_lderrno = B_FALSE;
1061 }
1062
1063 (void) snprintf(errstr, sizeof (errstr),
1064 "%s", ldap_err2string(Errno));
1065 err = strdup(errstr);
1066 if (pwd_status != NS_PASSWD_GOOD) {
1067 MKERROR_PWD_MGMT(*errorp, Errno, err,
1068 pwd_status, 0, NULL);
1069 } else {
1070 MKERROR(LOG_INFO, *errorp, Errno, err, NULL);
1071 }
1072 if (conn_user != NULL &&
1073 (Errno == LDAP_SERVER_DOWN ||
1074 Errno == LDAP_CONNECT_ERROR)) {
1075 __s_api_conn_mt_close(conn_user, Errno, errorp);
1076 }
1077 return_rc = NS_LDAP_INTERNAL;
1078 new_state = W_EXIT;
1079 break;
1080 case W_ERROR:
1081 default:
1082 (void) sprintf(errstr,
1083 gettext("Internal write State machine exit"
1084 " (state = %d, rc = %d)."),
1085 err_state, return_rc);
1086 err = strdup(errstr);
1087 MKERROR(LOG_WARNING, *errorp, return_rc, err, NULL);
1088 new_state = W_EXIT;
1089 break;
1090 }
1091
1092 if (new_state == W_ERROR)
1093 err_state = state;
1094
1095 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
1096 __s_api_conn_mt_close(conn_user, 0, NULL);
1097 new_state = W_EXIT;
1098 }
1099
1100 state = new_state;
1101 }
1102
1103 /*
1104 * should never be here, the next line is to eliminating
1105 * lint message
1106 */
1107 return (NS_LDAP_INTERNAL);
1108 }
1109
1110
1111 /*ARGSUSED*/
1112 int
__ns_ldap_addAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1113 __ns_ldap_addAttr(
1114 const char *service,
1115 const char *dn,
1116 const ns_ldap_attr_t * const *attr,
1117 const ns_cred_t *cred,
1118 const int flags,
1119 ns_ldap_error_t ** errorp)
1120 {
1121 LDAPMod **mods;
1122 int rc = 0;
1123
1124 #ifdef DEBUG
1125 (void) fprintf(stderr, "__ns_ldap_addAttr START\n");
1126 #endif
1127 *errorp = NULL;
1128
1129 /* Sanity check */
1130 if ((attr == NULL) || (*attr == NULL) ||
1131 (dn == NULL) || (cred == NULL))
1132 return (NS_LDAP_INVALID_PARAM);
1133
1134 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1135 if (mods == NULL) {
1136 return (NS_LDAP_MEMORY);
1137 }
1138
1139 rc = write_state_machine(LDAP_REQ_MODIFY,
1140 (char *)dn, mods, cred, flags, errorp);
1141 freeModList(mods);
1142
1143 return (rc);
1144 }
1145
1146
1147 /*ARGSUSED*/
1148 int
__ns_ldap_delAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1149 __ns_ldap_delAttr(
1150 const char *service,
1151 const char *dn,
1152 const ns_ldap_attr_t * const *attr,
1153 const ns_cred_t *cred,
1154 const int flags,
1155 ns_ldap_error_t ** errorp)
1156 {
1157 LDAPMod **mods;
1158 int rc = 0;
1159
1160 #ifdef DEBUG
1161 (void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1162 #endif
1163 *errorp = NULL;
1164
1165 /* Sanity check */
1166 if ((attr == NULL) || (*attr == NULL) ||
1167 (dn == NULL) || (cred == NULL))
1168 return (NS_LDAP_INVALID_PARAM);
1169
1170 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1171 if (mods == NULL) {
1172 return (NS_LDAP_MEMORY);
1173 }
1174
1175 rc = write_state_machine(LDAP_REQ_MODIFY,
1176 (char *)dn, mods, cred, flags, errorp);
1177
1178 freeModList(mods);
1179 return (rc);
1180 }
1181
1182 /* Retrieve the admin bind password from the configuration, if allowed. */
1183 static int
get_admin_passwd(ns_cred_t * cred,ns_ldap_error_t ** errorp)1184 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
1185 {
1186 void **paramVal = NULL;
1187 int rc, ldaprc;
1188 char *modparamVal = NULL;
1189
1190 /*
1191 * For GSSAPI/Kerberos, host credential is used, no need to get
1192 * admin bind password
1193 */
1194 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
1195 return (NS_LDAP_SUCCESS);
1196
1197 /*
1198 * Retrieve admin bind password.
1199 * The admin bind password is available
1200 * only in the ldap_cachemgr process as
1201 * they are not exposed outside of that
1202 * process.
1203 */
1204 paramVal = NULL;
1205 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1206 ¶mVal, errorp)) != NS_LDAP_SUCCESS)
1207 return (ldaprc);
1208 if (paramVal == NULL || *paramVal == NULL) {
1209 rc = NS_LDAP_CONFIG;
1210 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
1211 gettext("Admin bind password not configured"));
1212 if (*errorp == NULL)
1213 rc = NS_LDAP_MEMORY;
1214 return (rc);
1215 }
1216 modparamVal = dvalue((char *)*paramVal);
1217 (void) memset(*paramVal, 0, strlen((char *)*paramVal));
1218 (void) __ns_ldap_freeParam(¶mVal);
1219 if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
1220 if (modparamVal != NULL)
1221 free(modparamVal);
1222 rc = NS_LDAP_CONFIG;
1223 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
1224 gettext("bind password not valid"));
1225 if (*errorp == NULL)
1226 rc = NS_LDAP_MEMORY;
1227 return (rc);
1228 }
1229
1230 cred->cred.unix_cred.passwd = modparamVal;
1231 return (NS_LDAP_SUCCESS);
1232 }
1233
1234 boolean_t
__ns_ldap_is_shadow_update_enabled(void)1235 __ns_ldap_is_shadow_update_enabled(void)
1236 {
1237 int **enable_shadow = NULL;
1238 ns_ldap_error_t *errorp = NULL;
1239
1240 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1241 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1242 if (errorp)
1243 (void) __ns_ldap_freeError(&errorp);
1244 return (B_FALSE);
1245 }
1246 if ((enable_shadow != NULL && *enable_shadow != NULL) &&
1247 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
1248 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1249 return (B_TRUE);
1250 }
1251 if (enable_shadow != NULL)
1252 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1253 return (B_FALSE);
1254 }
1255
1256 /*
1257 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
1258 * on the LDAP server. 'service' indicates the type of database entries
1259 * to modify. When the Native LDAP client is configured with 'shadow update
1260 * enabled', Shadowshadow(4) entries can only be modified by privileged users.
1261 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
1262 * for such a shadow(4) update, which would be forwarded to ldap_cachemgr
1263 * for performing the LDAP modify operation. ldap_cachemgr would call
1264 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
1265 * to identify itself, so that admin credential would be obtained and
1266 * the actual LDAP modify operation be done.
1267 */
1268 /*ARGSUSED*/
1269 int
__ns_ldap_repAttr(const char * service,const char * dn,const ns_ldap_attr_t * const * attr,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1270 __ns_ldap_repAttr(
1271 const char *service,
1272 const char *dn,
1273 const ns_ldap_attr_t * const *attr,
1274 const ns_cred_t *cred,
1275 const int flags,
1276 ns_ldap_error_t ** errorp)
1277 {
1278 LDAPMod **mods;
1279 int rc = 0;
1280 boolean_t priv;
1281 boolean_t shadow_update_enabled = B_FALSE;
1282
1283 #ifdef DEBUG
1284 (void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1285 #endif
1286 *errorp = NULL;
1287
1288 /* Sanity check */
1289 if (attr == NULL || *attr == NULL || dn == NULL)
1290 return (NS_LDAP_INVALID_PARAM);
1291
1292 /* Privileged shadow modify? */
1293 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
1294 strcmp(service, "shadow") == 0) {
1295
1296 /* Shadow update enabled ? If not, error out */
1297 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
1298 if (!shadow_update_enabled) {
1299 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
1300 gettext("Shadow Update is not enabled"));
1301 return (NS_LDAP_CONFIG);
1302 }
1303
1304 /* privileged shadow modify requires euid 0 or all zone privs */
1305 priv = (geteuid() == 0);
1306 if (!priv) {
1307 priv_set_t *ps = priv_allocset(); /* caller */
1308 priv_set_t *zs; /* zone */
1309
1310 (void) getppriv(PRIV_EFFECTIVE, ps);
1311 zs = priv_str_to_set("zone", ",", NULL);
1312 priv = priv_isequalset(ps, zs);
1313 priv_freeset(ps);
1314 priv_freeset(zs);
1315 }
1316 if (!priv)
1317 return (NS_LDAP_OP_FAILED);
1318
1319 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
1320 return (rc);
1321 }
1322
1323 if (cred == NULL)
1324 return (NS_LDAP_INVALID_PARAM);
1325
1326 /*
1327 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
1328 * ldap_cachemgr. We need to get the admin cred to do work.
1329 * If the caller is not ldap_cachemgr, but use the service
1330 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
1331 * as the admin cred is not available to the caller.
1332 */
1333 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
1334 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
1335 NS_LDAP_SUCCESS)
1336 return (rc);
1337 }
1338
1339 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1340 if (mods == NULL)
1341 return (NS_LDAP_MEMORY);
1342
1343 rc = write_state_machine(LDAP_REQ_MODIFY,
1344 (char *)dn, mods, cred, flags, errorp);
1345
1346 freeModList(mods);
1347 return (rc);
1348 }
1349
1350 /*ARGSUSED*/
1351 int
__ns_ldap_addEntry(const char * service,const char * dn,const ns_ldap_entry_t * entry,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1352 __ns_ldap_addEntry(
1353 const char *service,
1354 const char *dn,
1355 const ns_ldap_entry_t *entry,
1356 const ns_cred_t *cred,
1357 const int flags,
1358 ns_ldap_error_t ** errorp)
1359 {
1360 char *new_dn = NULL;
1361 LDAPMod **mods = NULL;
1362 const ns_ldap_attr_t * const *attr;
1363 int nAttr = 0;
1364 int rc = 0;
1365
1366 #ifdef DEBUG
1367 (void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1368 #endif
1369
1370 if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1371 return (NS_LDAP_INVALID_PARAM);
1372 *errorp = NULL;
1373
1374 /* Construct array of LDAPMod representing attributes of new entry. */
1375
1376 nAttr = entry->attr_count;
1377 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1378 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1379 nAttr, flags);
1380 if (mods == NULL) {
1381 return (NS_LDAP_MEMORY);
1382 }
1383
1384 rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1385 if (rc != NS_LDAP_SUCCESS) {
1386 freeModList(mods);
1387 return (rc);
1388 }
1389
1390 rc = write_state_machine(LDAP_REQ_ADD,
1391 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1392
1393 if (new_dn)
1394 free(new_dn);
1395 freeModList(mods);
1396 return (rc);
1397 }
1398
1399
1400 /*ARGSUSED*/
1401 int
__ns_ldap_delEntry(const char * service,const char * dn,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1402 __ns_ldap_delEntry(
1403 const char *service,
1404 const char *dn,
1405 const ns_cred_t *cred,
1406 const int flags,
1407 ns_ldap_error_t ** errorp)
1408 {
1409 int rc;
1410
1411 #ifdef DEBUG
1412 (void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1413 #endif
1414 if ((dn == NULL) || (cred == NULL))
1415 return (NS_LDAP_INVALID_PARAM);
1416
1417 *errorp = NULL;
1418
1419 rc = write_state_machine(LDAP_REQ_DELETE,
1420 (char *)dn, NULL, cred, flags, errorp);
1421
1422 return (rc);
1423 }
1424
1425 /*
1426 * Add Typed Entry Helper routines
1427 */
1428
1429 /*
1430 * Add Typed Entry Conversion routines
1431 */
1432
1433 static int
__s_add_attr(ns_ldap_entry_t * e,char * attrname,char * value)1434 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1435 {
1436 ns_ldap_attr_t *a;
1437 char *v;
1438
1439 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1440 if (a == NULL)
1441 return (NS_LDAP_MEMORY);
1442 a->attrname = strdup(attrname);
1443 if (a->attrname == NULL)
1444 return (NS_LDAP_MEMORY);
1445 a->attrvalue = (char **)calloc(1, sizeof (char **));
1446 if (a->attrvalue == NULL)
1447 return (NS_LDAP_MEMORY);
1448 a->value_count = 1;
1449 a->attrvalue[0] = NULL;
1450 v = strdup(value);
1451 if (v == NULL)
1452 return (NS_LDAP_MEMORY);
1453 a->attrvalue[0] = v;
1454 e->attr_pair[e->attr_count] = a;
1455 e->attr_count++;
1456 return (NS_LDAP_SUCCESS);
1457 }
1458
1459 static int
__s_add_attrlist(ns_ldap_entry_t * e,char * attrname,char ** argv)1460 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1461 {
1462 ns_ldap_attr_t *a;
1463 char *v;
1464 char **av;
1465 int i, j;
1466
1467 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1468 if (a == NULL)
1469 return (NS_LDAP_MEMORY);
1470 a->attrname = strdup(attrname);
1471 if (a->attrname == NULL)
1472 return (NS_LDAP_MEMORY);
1473
1474 for (i = 0, av = argv; *av != NULL; av++, i++)
1475 ;
1476
1477 a->attrvalue = (char **)calloc(i, sizeof (char *));
1478
1479 if (a->attrvalue == NULL)
1480 return (NS_LDAP_MEMORY);
1481
1482 a->value_count = i;
1483 for (j = 0; j < i; j++) {
1484 v = strdup(argv[j]);
1485 if (v == NULL)
1486 return (NS_LDAP_MEMORY);
1487 a->attrvalue[j] = v;
1488 }
1489 e->attr_pair[e->attr_count] = a;
1490 e->attr_count++;
1491 return (NS_LDAP_SUCCESS);
1492 }
1493
1494 static ns_ldap_entry_t *
__s_mk_entry(char ** objclass,int max_attr)1495 __s_mk_entry(char **objclass, int max_attr)
1496 {
1497 ns_ldap_entry_t *e;
1498 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1499 if (e == NULL)
1500 return (NULL);
1501 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1502 e->attr_pair = (ns_ldap_attr_t **)
1503 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1504 if (e->attr_pair == NULL) {
1505 free(e);
1506 return (NULL);
1507 }
1508 e->attr_count = 0;
1509 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1510 free(e->attr_pair);
1511 free(e);
1512 return (NULL);
1513 }
1514 return (e);
1515 }
1516
1517
1518 /*
1519 * Conversion: passwd
1520 * Input format: struct passwd
1521 * Exported objectclass: posixAccount
1522 */
1523 static int
__s_cvt_passwd(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1524 __s_cvt_passwd(const void *data, char **rdn,
1525 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1526 {
1527 ns_ldap_entry_t *e;
1528 int rc;
1529 char trdn[RDNSIZE];
1530 /* routine specific */
1531 struct passwd *ptr;
1532 int max_attr = 9;
1533 char ibuf[10];
1534 static char *oclist[] = {
1535 "posixAccount",
1536 "shadowAccount",
1537 "account",
1538 "top",
1539 NULL
1540 };
1541
1542 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1543 return (NS_LDAP_OP_FAILED);
1544 *entry = e = __s_mk_entry(oclist, max_attr);
1545 if (e == NULL)
1546 return (NS_LDAP_MEMORY);
1547
1548 /* Convert the structure */
1549 ptr = (struct passwd *)data;
1550
1551 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
1552 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
1553 __ns_ldap_freeEntry(e);
1554 *entry = NULL;
1555 return (NS_LDAP_INVALID_PARAM);
1556 }
1557
1558 /* Create an appropriate rdn */
1559 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1560 *rdn = strdup(trdn);
1561 if (*rdn == NULL) {
1562 __ns_ldap_freeEntry(e);
1563 *entry = NULL;
1564 return (NS_LDAP_MEMORY);
1565 }
1566
1567 /* Error check the data and add the attributes */
1568 rc = __s_add_attr(e, "uid", ptr->pw_name);
1569 if (rc != NS_LDAP_SUCCESS) {
1570 __s_cvt_freeEntryRdn(entry, rdn);
1571 return (rc);
1572 }
1573 rc = __s_add_attr(e, "cn", ptr->pw_name);
1574 if (rc != NS_LDAP_SUCCESS) {
1575 __s_cvt_freeEntryRdn(entry, rdn);
1576 return (rc);
1577 }
1578
1579 if (ptr->pw_passwd != NULL &&
1580 ptr->pw_passwd[0] != '\0') {
1581 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1582 if (rc != NS_LDAP_SUCCESS) {
1583 __s_cvt_freeEntryRdn(entry, rdn);
1584 return (rc);
1585 }
1586 }
1587
1588 (void) sprintf(ibuf, "%u", ptr->pw_uid);
1589 rc = __s_add_attr(e, "uidNumber", ibuf);
1590 if (rc != NS_LDAP_SUCCESS) {
1591 __s_cvt_freeEntryRdn(entry, rdn);
1592 return (rc);
1593 }
1594
1595 (void) sprintf(ibuf, "%u", ptr->pw_gid);
1596 rc = __s_add_attr(e, "gidNumber", ibuf);
1597 if (rc != NS_LDAP_SUCCESS) {
1598 __s_cvt_freeEntryRdn(entry, rdn);
1599 return (rc);
1600 }
1601 if (ptr->pw_gecos != NULL &&
1602 ptr->pw_gecos[0] != '\0') {
1603 rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1604 if (rc != NS_LDAP_SUCCESS) {
1605 __s_cvt_freeEntryRdn(entry, rdn);
1606 return (rc);
1607 }
1608 }
1609
1610 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1611 if (rc != NS_LDAP_SUCCESS) {
1612 __s_cvt_freeEntryRdn(entry, rdn);
1613 return (rc);
1614 }
1615 if (ptr->pw_shell != NULL &&
1616 ptr->pw_shell[0] != '\0') {
1617 rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1618 if (rc != NS_LDAP_SUCCESS) {
1619 __s_cvt_freeEntryRdn(entry, rdn);
1620 return (rc);
1621 }
1622 }
1623
1624 return (NS_LDAP_SUCCESS);
1625 }
1626
1627 /*
1628 * escape_str function escapes special characters in str and
1629 * copies to escstr string.
1630 *
1631 * return 0 for successful
1632 * 1 for fail
1633 */
escape_str(char * escstr,char * str)1634 static int escape_str(char *escstr, char *str)
1635 {
1636 int index = 0;
1637
1638 while ((*str != '\0') && (index < (RDNSIZE - 1))) {
1639 if (*str == '+' || *str == ';' || *str == '>' ||
1640 *str == '<' || *str == ',' || *str == '"' ||
1641 *str == '\\' || *str == '=' ||
1642 (*str == '#' && index == 0)) {
1643 *escstr++ = '\\';
1644 *escstr++ = *str++;
1645 index += 2;
1646 } else {
1647 *escstr++ = *str++;
1648 index++;
1649 }
1650 }
1651
1652 if (*str == '\0') {
1653 *escstr = '\0';
1654 return (0);
1655 } else {
1656 return (1);
1657 }
1658 }
1659
1660 /*
1661 * Conversion: project
1662 * Input format: struct project
1663 * Exported objectclass: SolarisProject
1664 */
1665 static int
__s_cvt_project(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1666 __s_cvt_project(const void *data, char **rdn,
1667 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1668 {
1669 ns_ldap_entry_t *e;
1670 int rc;
1671 char trdn[RDNSIZE];
1672
1673 /* routine specific */
1674 struct project *ptr;
1675 int max_attr = 9;
1676 char ibuf[11];
1677 static char *oclist[] = {
1678 "SolarisProject",
1679 "top",
1680 NULL
1681 };
1682
1683 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1684 return (NS_LDAP_OP_FAILED);
1685
1686 *entry = e = __s_mk_entry(oclist, max_attr);
1687 if (e == NULL)
1688 return (NS_LDAP_MEMORY);
1689
1690 /* Convert the structure */
1691 ptr = (struct project *)data;
1692
1693 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
1694 __ns_ldap_freeEntry(e);
1695 *entry = NULL;
1696 return (NS_LDAP_INVALID_PARAM);
1697 }
1698
1699 /* Create an appropriate rdn */
1700 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
1701 *rdn = strdup(trdn);
1702 if (*rdn == NULL) {
1703 __ns_ldap_freeEntry(e);
1704 *entry = NULL;
1705 return (NS_LDAP_MEMORY);
1706 }
1707
1708 /* Error check the data and add the attributes */
1709
1710 /* Project name */
1711 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
1712 if (rc != NS_LDAP_SUCCESS) {
1713 __s_cvt_freeEntryRdn(entry, rdn);
1714 return (rc);
1715 }
1716
1717 /*
1718 * Project ID:
1719 * ibuf is 11 chars big, which should be enough for string
1720 * representation of 32bit number + nul-car
1721 */
1722 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
1723 __s_cvt_freeEntryRdn(entry, rdn);
1724 return (NS_LDAP_INVALID_PARAM);
1725 }
1726 rc = __s_add_attr(e, "SolarisProjectID", ibuf);
1727 if (rc != NS_LDAP_SUCCESS) {
1728 __s_cvt_freeEntryRdn(entry, rdn);
1729 return (rc);
1730 }
1731
1732 /* Comment/Description */
1733 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
1734 rc = __s_add_attr(e, "description", ptr->pj_comment);
1735 if (rc != NS_LDAP_SUCCESS) {
1736 __s_cvt_freeEntryRdn(entry, rdn);
1737 return (rc);
1738 }
1739 }
1740
1741 /* Attributes */
1742 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
1743 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
1744 if (rc != NS_LDAP_SUCCESS) {
1745 __s_cvt_freeEntryRdn(entry, rdn);
1746 return (rc);
1747 }
1748 }
1749
1750 /* Users */
1751 if (ptr->pj_users != NULL) {
1752 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
1753 if (rc != NS_LDAP_SUCCESS) {
1754 __s_cvt_freeEntryRdn(entry, rdn);
1755 return (rc);
1756 }
1757 }
1758
1759 /* Groups */
1760 if (ptr->pj_groups != NULL) {
1761 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
1762 if (rc != NS_LDAP_SUCCESS) {
1763 __s_cvt_freeEntryRdn(entry, rdn);
1764 return (rc);
1765 }
1766 }
1767
1768
1769
1770 return (NS_LDAP_SUCCESS);
1771 }
1772 /*
1773 * Conversion: shadow
1774 * Input format: struct shadow
1775 * Exported objectclass: shadowAccount
1776 */
1777 static int
__s_cvt_shadow(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1778 __s_cvt_shadow(const void *data, char **rdn,
1779 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1780 {
1781 ns_ldap_entry_t *e;
1782 int rc;
1783 char trdn[RDNSIZE];
1784 /* routine specific */
1785 struct spwd *ptr;
1786 int max_attr = 10;
1787 char ibuf[10];
1788 static char *oclist[] = {
1789 "posixAccount",
1790 "shadowAccount",
1791 "account",
1792 "top",
1793 NULL
1794 };
1795
1796 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1797 return (NS_LDAP_OP_FAILED);
1798 *entry = e = __s_mk_entry(oclist, max_attr);
1799 if (e == NULL)
1800 return (NS_LDAP_MEMORY);
1801
1802 /* Convert the structure */
1803 ptr = (struct spwd *)data;
1804
1805 if (ptr->sp_namp == NULL) {
1806 __ns_ldap_freeEntry(e);
1807 *entry = NULL;
1808 return (NS_LDAP_INVALID_PARAM);
1809 }
1810
1811 /* Create an appropriate rdn */
1812 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1813 *rdn = strdup(trdn);
1814 if (*rdn == NULL) {
1815 __ns_ldap_freeEntry(e);
1816 *entry = NULL;
1817 return (NS_LDAP_MEMORY);
1818 }
1819
1820 /* Error check the data and add the attributes */
1821 rc = __s_add_attr(e, "uid", ptr->sp_namp);
1822 if (rc != NS_LDAP_SUCCESS) {
1823 __s_cvt_freeEntryRdn(entry, rdn);
1824 return (rc);
1825 }
1826
1827 if (ptr->sp_pwdp == NULL) {
1828 __s_cvt_freeEntryRdn(entry, rdn);
1829 return (NS_LDAP_INVALID_PARAM);
1830 } else {
1831 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1832 if (rc != NS_LDAP_SUCCESS) {
1833 __s_cvt_freeEntryRdn(entry, rdn);
1834 return (rc);
1835 }
1836 }
1837 if (ptr->sp_lstchg >= 0) {
1838 (void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1839 rc = __s_add_attr(e, "shadowLastChange", ibuf);
1840 if (rc != NS_LDAP_SUCCESS) {
1841 __s_cvt_freeEntryRdn(entry, rdn);
1842 return (rc);
1843 }
1844 }
1845 if (ptr->sp_min >= 0) {
1846 (void) sprintf(ibuf, "%d", ptr->sp_min);
1847 rc = __s_add_attr(e, "shadowMin", ibuf);
1848 if (rc != NS_LDAP_SUCCESS) {
1849 __s_cvt_freeEntryRdn(entry, rdn);
1850 return (rc);
1851 }
1852 }
1853 if (ptr->sp_max >= 0) {
1854 (void) sprintf(ibuf, "%d", ptr->sp_max);
1855 rc = __s_add_attr(e, "shadowMax", ibuf);
1856 if (rc != NS_LDAP_SUCCESS) {
1857 __s_cvt_freeEntryRdn(entry, rdn);
1858 return (rc);
1859 }
1860 }
1861 if (ptr->sp_warn >= 0) {
1862 (void) sprintf(ibuf, "%d", ptr->sp_warn);
1863 rc = __s_add_attr(e, "shadowWarning", ibuf);
1864 if (rc != NS_LDAP_SUCCESS) {
1865 __s_cvt_freeEntryRdn(entry, rdn);
1866 return (rc);
1867 }
1868 }
1869 if (ptr->sp_inact >= 0) {
1870 (void) sprintf(ibuf, "%d", ptr->sp_inact);
1871 rc = __s_add_attr(e, "shadowInactive", ibuf);
1872 if (rc != NS_LDAP_SUCCESS) {
1873 __s_cvt_freeEntryRdn(entry, rdn);
1874 return (rc);
1875 }
1876 }
1877 if (ptr->sp_expire >= 0) {
1878 (void) sprintf(ibuf, "%d", ptr->sp_expire);
1879 rc = __s_add_attr(e, "shadowExpire", ibuf);
1880 if (rc != NS_LDAP_SUCCESS) {
1881 __s_cvt_freeEntryRdn(entry, rdn);
1882 return (rc);
1883 }
1884 }
1885 (void) sprintf(ibuf, "%d", ptr->sp_flag);
1886 rc = __s_add_attr(e, "shadowFlag", ibuf);
1887 if (rc != NS_LDAP_SUCCESS) {
1888 __s_cvt_freeEntryRdn(entry, rdn);
1889 return (rc);
1890 }
1891
1892 return (NS_LDAP_SUCCESS);
1893 }
1894
1895
1896 /*
1897 * Conversion: group
1898 * Input format: struct group
1899 * Exported objectclass: posixGroup
1900 */
1901 static int
__s_cvt_group(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1902 __s_cvt_group(const void *data, char **rdn,
1903 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1904 {
1905 ns_ldap_entry_t *e;
1906 int rc;
1907 char trdn[RDNSIZE];
1908 /* routine specific */
1909 struct group *ptr;
1910 int i, j, k;
1911 char **nm, **lm;
1912 int max_attr = 4;
1913 char ibuf[10];
1914 static char *oclist[] = {
1915 "posixGroup",
1916 "top",
1917 NULL
1918 };
1919
1920 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1921 return (NS_LDAP_OP_FAILED);
1922 *entry = e = __s_mk_entry(oclist, max_attr);
1923 if (e == NULL)
1924 return (NS_LDAP_MEMORY);
1925
1926 /* Convert the structure */
1927 ptr = (struct group *)data;
1928
1929 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
1930 __ns_ldap_freeEntry(e);
1931 *entry = NULL;
1932 return (NS_LDAP_INVALID_PARAM);
1933 }
1934
1935 /* Create an appropriate rdn */
1936 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1937 *rdn = strdup(trdn);
1938 if (*rdn == NULL) {
1939 __ns_ldap_freeEntry(e);
1940 *entry = NULL;
1941 return (NS_LDAP_MEMORY);
1942 }
1943
1944 /* Error check the data and add the attributes */
1945 rc = __s_add_attr(e, "cn", ptr->gr_name);
1946 if (rc != NS_LDAP_SUCCESS) {
1947 __s_cvt_freeEntryRdn(entry, rdn);
1948 return (rc);
1949 }
1950
1951 (void) sprintf(ibuf, "%u", ptr->gr_gid);
1952 rc = __s_add_attr(e, "gidNumber", ibuf);
1953 if (rc != NS_LDAP_SUCCESS) {
1954 __s_cvt_freeEntryRdn(entry, rdn);
1955 return (rc);
1956 }
1957 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1958 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1959 if (rc != NS_LDAP_SUCCESS) {
1960 __s_cvt_freeEntryRdn(entry, rdn);
1961 return (rc);
1962 }
1963 }
1964
1965 if (ptr->gr_mem && ptr->gr_mem[0]) {
1966 lm = ptr->gr_mem;
1967 for (i = 0; *lm; i++, lm++)
1968 ;
1969 lm = ptr->gr_mem;
1970 nm = (char **)calloc(i+2, sizeof (char *));
1971 if (nm == NULL) {
1972 __s_cvt_freeEntryRdn(entry, rdn);
1973 return (NS_LDAP_MEMORY);
1974 }
1975 for (j = 0; j < i; j++) {
1976 nm[j] = strdup(lm[j]);
1977 if (nm[j] == NULL) {
1978 for (k = 0; k < j; k++)
1979 free(nm[k]);
1980 free(nm);
1981 __s_cvt_freeEntryRdn(entry, rdn);
1982 return (NS_LDAP_MEMORY);
1983 }
1984 }
1985 rc = __s_add_attrlist(e, "memberUid", nm);
1986 for (j = 0; j < i; j++) {
1987 free(nm[j]);
1988 }
1989 free(nm);
1990 nm = NULL;
1991 if (rc != NS_LDAP_SUCCESS) {
1992 __s_cvt_freeEntryRdn(entry, rdn);
1993 return (rc);
1994 }
1995 }
1996
1997 return (NS_LDAP_SUCCESS);
1998 }
1999
2000 /*
2001 * Conversion: hosts
2002 * Input format: struct hostent
2003 * Exported objectclass: ipHost
2004 */
2005 static int
__s_cvt_hosts(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2006 __s_cvt_hosts(const void *data, char **rdn,
2007 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2008 {
2009 ns_ldap_entry_t *e;
2010 int rc;
2011 char trdn[RDNSIZE];
2012 /* routine specific */
2013 struct hostent *ptr;
2014 int max_attr = 6;
2015 int i, j, k;
2016 char **nm, **lm;
2017 static char *oclist[] = {
2018 "ipHost",
2019 "device",
2020 "top",
2021 NULL
2022 };
2023
2024 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2025 return (NS_LDAP_OP_FAILED);
2026 *entry = e = __s_mk_entry(oclist, max_attr);
2027 if (e == NULL)
2028 return (NS_LDAP_MEMORY);
2029
2030 /* Convert the structure */
2031 ptr = (struct hostent *)data;
2032
2033 if (ptr->h_name == NULL ||
2034 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == '\0') {
2035 __ns_ldap_freeEntry(e);
2036 *entry = NULL;
2037 return (NS_LDAP_INVALID_PARAM);
2038 }
2039
2040 /* Create an appropriate rdn */
2041 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
2042 ptr->h_name, ptr->h_addr_list[0]);
2043 *rdn = strdup(trdn);
2044 if (*rdn == NULL) {
2045 __ns_ldap_freeEntry(e);
2046 *entry = NULL;
2047 return (NS_LDAP_MEMORY);
2048 }
2049
2050 /* Error check the data and add the attributes */
2051 if (ptr->h_aliases && ptr->h_aliases[0]) {
2052 lm = ptr->h_aliases;
2053 /*
2054 * If there is a description, 'i' will contain
2055 * the index of the description in the aliases list
2056 */
2057 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
2058 ;
2059 lm = ptr->h_aliases;
2060 nm = (char **)calloc(i+2, sizeof (char *));
2061 if (nm == NULL) {
2062 __s_cvt_freeEntryRdn(entry, rdn);
2063 return (NS_LDAP_MEMORY);
2064 }
2065 nm[0] = ptr->h_name;
2066 for (j = 0; j < i; j++)
2067 nm[j+1] = ptr->h_aliases[j];
2068
2069 rc = __s_add_attrlist(e, "cn", nm);
2070
2071 if (rc != NS_LDAP_SUCCESS) {
2072 __s_cvt_freeEntryRdn(entry, rdn);
2073 free(nm);
2074 return (rc);
2075 }
2076
2077 if (lm[i] && lm[i][0] == '#') {
2078 nm[0] = &(lm[i][1]);
2079 nm[1] = NULL;
2080 rc = __s_add_attrlist(e, "description", nm);
2081 }
2082 free(nm);
2083 nm = NULL;
2084 if (rc != NS_LDAP_SUCCESS) {
2085 __s_cvt_freeEntryRdn(entry, rdn);
2086 return (rc);
2087 }
2088 } else {
2089 rc = __s_add_attr(e, "cn", ptr->h_name);
2090 if (rc != NS_LDAP_SUCCESS) {
2091 __s_cvt_freeEntryRdn(entry, rdn);
2092 return (rc);
2093 }
2094 }
2095
2096 if (ptr->h_addr_list && ptr->h_addr_list[0]) {
2097 lm = ptr->h_addr_list;
2098 for (i = 0; *lm; i++, lm++)
2099 ;
2100 lm = ptr->h_addr_list;
2101 nm = (char **)calloc(i+2, sizeof (char *));
2102 if (nm == NULL) {
2103 __s_cvt_freeEntryRdn(entry, rdn);
2104 return (NS_LDAP_MEMORY);
2105 }
2106 for (j = 0; j < i; j++) {
2107 nm[j] = strdup(lm[j]);
2108 if (nm[j] == NULL) {
2109 for (k = 0; k < j; k++)
2110 free(nm[k]);
2111 free(nm);
2112 __s_cvt_freeEntryRdn(entry, rdn);
2113 return (NS_LDAP_MEMORY);
2114 }
2115 }
2116 rc = __s_add_attrlist(e, "ipHostNumber", nm);
2117 for (j = 0; j < i; j++) {
2118 free(nm[j]);
2119 }
2120 free(nm);
2121 nm = NULL;
2122 if (rc != NS_LDAP_SUCCESS) {
2123 __s_cvt_freeEntryRdn(entry, rdn);
2124 return (rc);
2125 }
2126 } else {
2127 __s_cvt_freeEntryRdn(entry, rdn);
2128 return (NS_LDAP_INVALID_PARAM);
2129 }
2130
2131 return (NS_LDAP_SUCCESS);
2132 }
2133
2134 /*
2135 * Conversion: rpc
2136 * Input format: struct rpcent
2137 * Exported objectclass: oncRpc
2138 */
2139 static int
__s_cvt_rpc(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2140 __s_cvt_rpc(const void *data, char **rdn,
2141 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2142 {
2143 ns_ldap_entry_t *e;
2144 int rc;
2145 char trdn[RDNSIZE];
2146 /* routine specific */
2147 struct rpcent *ptr;
2148 int max_attr = 3;
2149 int i, j;
2150 char **nm;
2151 char ibuf[10];
2152 static char *oclist[] = {
2153 "oncRpc",
2154 "top",
2155 NULL
2156 };
2157
2158 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2159 return (NS_LDAP_OP_FAILED);
2160 *entry = e = __s_mk_entry(oclist, max_attr);
2161 if (e == NULL)
2162 return (NS_LDAP_MEMORY);
2163
2164 /* Convert the structure */
2165 ptr = (struct rpcent *)data;
2166
2167 if (ptr->r_name == NULL || ptr->r_number < 0) {
2168 __ns_ldap_freeEntry(e);
2169 *entry = NULL;
2170 return (NS_LDAP_INVALID_PARAM);
2171 }
2172
2173 /* Create an appropriate rdn */
2174 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
2175 *rdn = strdup(trdn);
2176 if (*rdn == NULL) {
2177 __ns_ldap_freeEntry(e);
2178 *entry = NULL;
2179 return (NS_LDAP_MEMORY);
2180 }
2181
2182 /* Error check the data and add the attributes */
2183 if (ptr->r_aliases && ptr->r_aliases[0]) {
2184 nm = ptr->r_aliases;
2185 for (i = 0; *nm; i++, nm++)
2186 ;
2187 nm = (char **)calloc(i+2, sizeof (char *));
2188 if (nm == NULL) {
2189 __s_cvt_freeEntryRdn(entry, rdn);
2190 return (NS_LDAP_MEMORY);
2191 }
2192 nm[0] = ptr->r_name;
2193 for (j = 0; j < i; j++)
2194 nm[j+1] = ptr->r_aliases[j];
2195
2196 rc = __s_add_attrlist(e, "cn", nm);
2197 free(nm);
2198 nm = NULL;
2199 if (rc != NS_LDAP_SUCCESS) {
2200 __s_cvt_freeEntryRdn(entry, rdn);
2201 return (rc);
2202 }
2203 } else {
2204 rc = __s_add_attr(e, "cn", ptr->r_name);
2205 if (rc != NS_LDAP_SUCCESS) {
2206 __s_cvt_freeEntryRdn(entry, rdn);
2207 return (rc);
2208 }
2209 }
2210
2211 if (ptr->r_number >= 0) {
2212 (void) sprintf(ibuf, "%d", ptr->r_number);
2213 rc = __s_add_attr(e, "oncRpcNumber", ibuf);
2214 if (rc != NS_LDAP_SUCCESS) {
2215 __s_cvt_freeEntryRdn(entry, rdn);
2216 return (rc);
2217 }
2218 }
2219
2220 return (NS_LDAP_SUCCESS);
2221
2222 }
2223
2224 /*
2225 * Conversion: protocols
2226 * Input format: struct protoent
2227 * Exported objectclass: ipProtocol
2228 */
2229 static int
__s_cvt_protocols(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2230 __s_cvt_protocols(const void *data, char **rdn,
2231 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2232 {
2233 ns_ldap_entry_t *e;
2234 int rc;
2235 char trdn[RDNSIZE];
2236 /* routine specific */
2237 struct protoent *ptr;
2238 int max_attr = 3;
2239 int i, j;
2240 char ibuf[10];
2241 char **nm;
2242 static char *oclist[] = {
2243 "ipProtocol",
2244 "top",
2245 NULL
2246 };
2247
2248 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2249 return (NS_LDAP_OP_FAILED);
2250 *entry = e = __s_mk_entry(oclist, max_attr);
2251 if (e == NULL)
2252 return (NS_LDAP_MEMORY);
2253
2254 /* Convert the structure */
2255 ptr = (struct protoent *)data;
2256
2257 if (ptr->p_name == NULL || ptr->p_proto < 0) {
2258 __ns_ldap_freeEntry(e);
2259 *entry = NULL;
2260 return (NS_LDAP_INVALID_PARAM);
2261 }
2262
2263 /* Create an appropriate rdn */
2264 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
2265 *rdn = strdup(trdn);
2266 if (*rdn == NULL) {
2267 __ns_ldap_freeEntry(e);
2268 *entry = NULL;
2269 return (NS_LDAP_MEMORY);
2270 }
2271
2272 /* Error check the data and add the attributes */
2273 if (ptr->p_aliases && ptr->p_aliases[0]) {
2274 nm = ptr->p_aliases;
2275 for (i = 0; *nm; i++, nm++)
2276 ;
2277 nm = (char **)calloc(i+2, sizeof (char *));
2278 if (nm == NULL) {
2279 __s_cvt_freeEntryRdn(entry, rdn);
2280 return (NS_LDAP_MEMORY);
2281 }
2282 nm[0] = ptr->p_name;
2283 for (j = 0; j < i; j++)
2284 nm[j+1] = ptr->p_aliases[j];
2285
2286 rc = __s_add_attrlist(e, "cn", nm);
2287 free(nm);
2288 nm = NULL;
2289 if (rc != NS_LDAP_SUCCESS) {
2290 __s_cvt_freeEntryRdn(entry, rdn);
2291 return (rc);
2292 }
2293 } else {
2294 rc = __s_add_attr(e, "cn", ptr->p_name);
2295 if (rc != NS_LDAP_SUCCESS) {
2296 __s_cvt_freeEntryRdn(entry, rdn);
2297 return (rc);
2298 }
2299 }
2300
2301 (void) sprintf(ibuf, "%d", ptr->p_proto);
2302 rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
2303 if (rc != NS_LDAP_SUCCESS) {
2304 __s_cvt_freeEntryRdn(entry, rdn);
2305 return (rc);
2306 }
2307
2308 return (NS_LDAP_SUCCESS);
2309
2310 }
2311
2312 /*
2313 * Conversion: services
2314 * Input format: struct servent
2315 * Exported objectclass: ipService
2316 */
2317 static int
__s_cvt_services(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2318 __s_cvt_services(const void *data, char **rdn,
2319 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2320 {
2321 ns_ldap_entry_t *e;
2322 int rc;
2323 char trdn[RDNSIZE];
2324 char esc_str[RDNSIZE];
2325 /* routine specific */
2326 struct servent *ptr;
2327 int max_attr = 4;
2328 int i, j;
2329 char ibuf[10];
2330 char **nm;
2331 static char *oclist[] = {
2332 "ipService",
2333 "top",
2334 NULL
2335 };
2336
2337 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2338 return (NS_LDAP_OP_FAILED);
2339 *entry = e = __s_mk_entry(oclist, max_attr);
2340 if (e == NULL)
2341 return (NS_LDAP_MEMORY);
2342
2343 /* Convert the structure */
2344 ptr = (struct servent *)data;
2345
2346 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == '\0') {
2347 __ns_ldap_freeEntry(e);
2348 *entry = NULL;
2349 return (NS_LDAP_INVALID_PARAM);
2350 }
2351
2352 /*
2353 * Escape special characters in service name.
2354 */
2355 if (escape_str(esc_str, ptr->s_name) != 0) {
2356 __ns_ldap_freeEntry(e);
2357 *entry = NULL;
2358 return (NS_LDAP_INVALID_PARAM);
2359 }
2360
2361 /* Create an appropriate rdn */
2362 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
2363 esc_str, ptr->s_proto);
2364
2365 *rdn = strdup(trdn);
2366 if (*rdn == NULL) {
2367 __ns_ldap_freeEntry(e);
2368 *entry = NULL;
2369 return (NS_LDAP_MEMORY);
2370 }
2371
2372 /* Error check the data and add the attributes */
2373 if (ptr->s_aliases && ptr->s_aliases[0]) {
2374 nm = ptr->s_aliases;
2375 for (i = 0; *nm; i++, nm++)
2376 ;
2377 nm = (char **)calloc(i+2, sizeof (char *));
2378 if (nm == NULL) {
2379 __s_cvt_freeEntryRdn(entry, rdn);
2380 return (NS_LDAP_MEMORY);
2381 }
2382 nm[0] = ptr->s_name;
2383 for (j = 0; j < i; j++)
2384 nm[j+1] = ptr->s_aliases[j];
2385
2386 rc = __s_add_attrlist(e, "cn", nm);
2387 free(nm);
2388 nm = NULL;
2389 if (rc != NS_LDAP_SUCCESS) {
2390 __s_cvt_freeEntryRdn(entry, rdn);
2391 return (rc);
2392 }
2393 } else {
2394 rc = __s_add_attr(e, "cn", ptr->s_name);
2395 if (rc != NS_LDAP_SUCCESS) {
2396 __s_cvt_freeEntryRdn(entry, rdn);
2397 return (rc);
2398 }
2399 }
2400
2401 (void) sprintf(ibuf, "%d", ptr->s_port);
2402 rc = __s_add_attr(e, "ipServicePort", ibuf);
2403 if (rc != NS_LDAP_SUCCESS) {
2404 __s_cvt_freeEntryRdn(entry, rdn);
2405 return (rc);
2406 }
2407 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
2408 if (rc != NS_LDAP_SUCCESS) {
2409 __s_cvt_freeEntryRdn(entry, rdn);
2410 return (rc);
2411 }
2412
2413 return (NS_LDAP_SUCCESS);
2414 }
2415
2416 /*
2417 * Conversion: networks
2418 * Input format: struct netent
2419 * Exported objectclass: ipNetwork
2420 */
2421 static int
__s_cvt_networks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2422 __s_cvt_networks(const void *data, char **rdn,
2423 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2424 {
2425 ns_ldap_entry_t *e;
2426 int rc;
2427 char trdn[RDNSIZE];
2428 /* routine specific */
2429 struct netent *ptr;
2430 int max_attr = 4;
2431 int i, j;
2432 char cp[64];
2433 char **nm;
2434 static char *oclist[] = {
2435 "ipNetwork",
2436 "top",
2437 NULL
2438 };
2439
2440 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2441 return (NS_LDAP_OP_FAILED);
2442 *entry = e = __s_mk_entry(oclist, max_attr);
2443 if (e == NULL)
2444 return (NS_LDAP_MEMORY);
2445
2446 /* Convert the structure */
2447 ptr = (struct netent *)data;
2448
2449 if (ptr->n_name == NULL || ptr->n_net == 0) {
2450 __ns_ldap_freeEntry(e);
2451 *entry = NULL;
2452 return (NS_LDAP_INVALID_PARAM);
2453 }
2454
2455 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2456 (ptr->n_net & 0xFF000000) >> 24,
2457 (ptr->n_net & 0x00FF0000) >> 16,
2458 (ptr->n_net & 0x0000FF00) >> 8,
2459 (ptr->n_net & 0x000000FF));
2460
2461 /* Create an appropriate rdn */
2462 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2463 *rdn = strdup(trdn);
2464 if (*rdn == NULL) {
2465 __ns_ldap_freeEntry(e);
2466 *entry = NULL;
2467 return (NS_LDAP_MEMORY);
2468 }
2469
2470 /* Error check the data and add the attributes */
2471 if (ptr->n_aliases && ptr->n_aliases[0]) {
2472 nm = ptr->n_aliases;
2473 for (i = 0; *nm; i++, nm++)
2474 ;
2475 nm = (char **)calloc(i+2, sizeof (char *));
2476 if (nm == NULL) {
2477 __s_cvt_freeEntryRdn(entry, rdn);
2478 return (NS_LDAP_MEMORY);
2479 }
2480 nm[0] = ptr->n_name;
2481 for (j = 0; j < i; j++)
2482 nm[j+1] = ptr->n_aliases[j];
2483
2484 rc = __s_add_attrlist(e, "cn", nm);
2485 free(nm);
2486 nm = NULL;
2487 if (rc != NS_LDAP_SUCCESS) {
2488 __s_cvt_freeEntryRdn(entry, rdn);
2489 return (rc);
2490 }
2491 } else {
2492 rc = __s_add_attr(e, "cn", ptr->n_name);
2493 if (rc != NS_LDAP_SUCCESS) {
2494 __s_cvt_freeEntryRdn(entry, rdn);
2495 return (rc);
2496 }
2497 }
2498
2499 rc = __s_add_attr(e, "ipNetworkNumber", cp);
2500 if (rc != NS_LDAP_SUCCESS) {
2501 __s_cvt_freeEntryRdn(entry, rdn);
2502 return (rc);
2503 }
2504
2505 return (NS_LDAP_SUCCESS);
2506
2507 }
2508 /*
2509 * Conversion: netmasks
2510 * Input format: struct _ns_netmasks
2511 * Exported objectclass: ipNetwork
2512 */
2513 static int
__s_cvt_netmasks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2514 __s_cvt_netmasks(const void *data, char **rdn,
2515 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2516 {
2517 ns_ldap_entry_t *e;
2518 int rc;
2519 char trdn[RDNSIZE];
2520 /* routine specific */
2521 struct _ns_netmasks *ptr;
2522 int max_attr = 4;
2523 static char *oclist[] = {
2524 "ipNetwork",
2525 "top",
2526 NULL
2527 };
2528
2529 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2530 return (NS_LDAP_OP_FAILED);
2531 *entry = e = __s_mk_entry(oclist, max_attr);
2532 if (e == NULL)
2533 return (NS_LDAP_MEMORY);
2534
2535 /* Convert the structure */
2536 ptr = (struct _ns_netmasks *)data;
2537
2538 if (ptr->netnumber == NULL) {
2539 __ns_ldap_freeEntry(e);
2540 *entry = NULL;
2541 return (NS_LDAP_INVALID_PARAM);
2542 }
2543
2544 /* Create an appropriate rdn */
2545 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2546 *rdn = strdup(trdn);
2547 if (*rdn == NULL) {
2548 __ns_ldap_freeEntry(e);
2549 *entry = NULL;
2550 return (NS_LDAP_MEMORY);
2551 }
2552
2553 /* Error check the data and add the attributes */
2554 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2555 if (rc != NS_LDAP_SUCCESS) {
2556 __s_cvt_freeEntryRdn(entry, rdn);
2557 return (rc);
2558 }
2559
2560 if (ptr->netmask != '\0') {
2561 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2562 if (rc != NS_LDAP_SUCCESS) {
2563 __s_cvt_freeEntryRdn(entry, rdn);
2564 return (rc);
2565 }
2566 }
2567
2568 return (NS_LDAP_SUCCESS);
2569
2570 }
2571 /*
2572 * Conversion: netgroups
2573 * Input format: struct _ns_netgroups
2574 * Exported objectclass: nisNetgroup
2575 */
2576 static int
__s_cvt_netgroups(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2577 __s_cvt_netgroups(const void *data, char **rdn,
2578 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2579 {
2580 ns_ldap_entry_t *e;
2581 int rc;
2582 char trdn[RDNSIZE];
2583 /* routine specific */
2584 struct _ns_netgroups *ptr;
2585 int max_attr = 6;
2586 int i, j;
2587 char **nm;
2588 static char *oclist[] = {
2589 "nisNetgroup",
2590 "top",
2591 NULL
2592 };
2593
2594 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2595 return (NS_LDAP_OP_FAILED);
2596 *entry = e = __s_mk_entry(oclist, max_attr);
2597 if (e == NULL)
2598 return (NS_LDAP_MEMORY);
2599
2600 /* Convert the structure */
2601 ptr = (struct _ns_netgroups *)data;
2602
2603 if (ptr->name == NULL) {
2604 __ns_ldap_freeEntry(e);
2605 *entry = NULL;
2606 return (NS_LDAP_INVALID_PARAM);
2607 }
2608
2609 /* Create an appropriate rdn */
2610 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2611 *rdn = strdup(trdn);
2612 if (*rdn == NULL) {
2613 __ns_ldap_freeEntry(e);
2614 *entry = NULL;
2615 return (NS_LDAP_MEMORY);
2616 }
2617
2618 if (ptr->name != '\0') {
2619 rc = __s_add_attr(e, "cn", ptr->name);
2620 if (rc != NS_LDAP_SUCCESS) {
2621 __s_cvt_freeEntryRdn(entry, rdn);
2622 return (rc);
2623 }
2624 }
2625
2626 /* Error check the data and add the attributes */
2627 if (ptr->triplet && ptr->triplet[0]) {
2628 nm = ptr->triplet;
2629 for (i = 0; *nm; i++, nm++)
2630 ;
2631 nm = (char **)calloc(i+2, sizeof (char *));
2632 if (nm == NULL) {
2633 __s_cvt_freeEntryRdn(entry, rdn);
2634 return (NS_LDAP_MEMORY);
2635 }
2636 for (j = 0; j < i; j++)
2637 nm[j] = ptr->triplet[j];
2638
2639 rc = __s_add_attrlist(e, "nisNetgroupTriple", nm);
2640 free(nm);
2641 nm = NULL;
2642 if (rc != NS_LDAP_SUCCESS) {
2643 __s_cvt_freeEntryRdn(entry, rdn);
2644 return (rc);
2645 }
2646 }
2647 if (ptr->netgroup && ptr->netgroup[0]) {
2648 nm = ptr->netgroup;
2649 for (i = 0; *nm; i++, nm++)
2650 ;
2651 nm = (char **)calloc(i+2, sizeof (char *));
2652 if (nm == NULL) {
2653 __s_cvt_freeEntryRdn(entry, rdn);
2654 return (NS_LDAP_MEMORY);
2655 }
2656 for (j = 0; j < i; j++)
2657 nm[j] = ptr->netgroup[j];
2658
2659 rc = __s_add_attrlist(e, "memberNisNetgroup", nm);
2660 free(nm);
2661 nm = NULL;
2662 if (rc != NS_LDAP_SUCCESS) {
2663 __s_cvt_freeEntryRdn(entry, rdn);
2664 return (rc);
2665 }
2666 }
2667 return (NS_LDAP_SUCCESS);
2668 }
2669 /*
2670 * Conversion: bootparams
2671 * Input format: struct _ns_bootp
2672 * Exported objectclass: bootableDevice, device
2673 */
2674 static int
__s_cvt_bootparams(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2675 __s_cvt_bootparams(const void *data, char **rdn,
2676 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2677 {
2678 ns_ldap_entry_t *e;
2679 int rc;
2680 char trdn[RDNSIZE];
2681 /* routine specific */
2682 struct _ns_bootp *ptr;
2683 int max_attr = 4;
2684 int i, j;
2685 char **nm;
2686 static char *oclist[] = {
2687 "bootableDevice",
2688 "device",
2689 "top",
2690 NULL
2691 };
2692
2693 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2694 return (NS_LDAP_OP_FAILED);
2695 *entry = e = __s_mk_entry(oclist, max_attr);
2696 if (e == NULL)
2697 return (NS_LDAP_MEMORY);
2698
2699 /* Convert the structure */
2700 ptr = (struct _ns_bootp *)data;
2701
2702 if (ptr->name == NULL) {
2703 __ns_ldap_freeEntry(e);
2704 *entry = NULL;
2705 return (NS_LDAP_INVALID_PARAM);
2706 }
2707
2708 /* Create an appropriate rdn */
2709 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2710 *rdn = strdup(trdn);
2711 if (*rdn == NULL) {
2712 __ns_ldap_freeEntry(e);
2713 *entry = NULL;
2714 return (NS_LDAP_MEMORY);
2715 }
2716
2717 if (ptr->name != '\0') {
2718 rc = __s_add_attr(e, "cn", ptr->name);
2719 if (rc != NS_LDAP_SUCCESS) {
2720 __s_cvt_freeEntryRdn(entry, rdn);
2721 return (rc);
2722 }
2723 }
2724
2725 /* Error check the data and add the attributes */
2726 if (ptr->param && ptr->param[0]) {
2727 nm = ptr->param;
2728 for (i = 0; *nm; i++, nm++)
2729 ;
2730 nm = (char **)calloc(i+2, sizeof (char *));
2731 if (nm == NULL) {
2732 __s_cvt_freeEntryRdn(entry, rdn);
2733 return (NS_LDAP_MEMORY);
2734 }
2735 for (j = 0; j < i; j++)
2736 nm[j] = ptr->param[j];
2737
2738 rc = __s_add_attrlist(e, "bootParameter", nm);
2739 free(nm);
2740 nm = NULL;
2741 if (rc != NS_LDAP_SUCCESS) {
2742 __s_cvt_freeEntryRdn(entry, rdn);
2743 return (rc);
2744 }
2745 }
2746
2747 return (NS_LDAP_SUCCESS);
2748
2749 }
2750 /*
2751 * Conversion: ethers
2752 * Input format: struct _ns_ethers
2753 * Exported objectclass: ieee802Device, device
2754 */
2755 static int
__s_cvt_ethers(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2756 __s_cvt_ethers(const void *data, char **rdn,
2757 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2758 {
2759 ns_ldap_entry_t *e;
2760 int rc;
2761 char trdn[RDNSIZE];
2762 /* routine specific */
2763 struct _ns_ethers *ptr;
2764 int max_attr = 4;
2765 static char *oclist[] = {
2766 "ieee802Device",
2767 "device",
2768 "top",
2769 NULL
2770 };
2771
2772 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2773 return (NS_LDAP_OP_FAILED);
2774 *entry = e = __s_mk_entry(oclist, max_attr);
2775 if (e == NULL)
2776 return (NS_LDAP_MEMORY);
2777
2778 /* Convert the structure */
2779 ptr = (struct _ns_ethers *)data;
2780
2781 if (ptr->name == NULL || ptr->ether == '\0') {
2782 __ns_ldap_freeEntry(e);
2783 *entry = NULL;
2784 return (NS_LDAP_INVALID_PARAM);
2785 }
2786
2787 /* Create an appropriate rdn */
2788 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2789 *rdn = strdup(trdn);
2790 if (*rdn == NULL) {
2791 __ns_ldap_freeEntry(e);
2792 *entry = NULL;
2793 return (NS_LDAP_MEMORY);
2794 }
2795
2796 /* Error check the data and add the attributes */
2797 rc = __s_add_attr(e, "cn", ptr->name);
2798 if (rc != NS_LDAP_SUCCESS) {
2799 __s_cvt_freeEntryRdn(entry, rdn);
2800 return (rc);
2801 }
2802
2803 rc = __s_add_attr(e, "macAddress", ptr->ether);
2804 if (rc != NS_LDAP_SUCCESS) {
2805 __s_cvt_freeEntryRdn(entry, rdn);
2806 return (rc);
2807 }
2808
2809 return (NS_LDAP_SUCCESS);
2810 }
2811 /*
2812 * This function is used when processing an ethers (objectclass: ieee802Device)
2813 * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2814 * already found in LDAP. Since both ethers and bootparams share the same
2815 * LDAP container, we want to check that the entry found in LDAP is:
2816 * - either the same entry (same cn, same objectclass): we don't do anything
2817 * in this case
2818 * - or an entry which does not have the objectclass we are interesting in:
2819 * in this case, we modify the existing entry by adding the relevant
2820 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2821 * from the attribute list previously computing by the relevant conversion
2822 * function.
2823 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams()
2824 * we know that there is only 1 more attribute today to add (macAddress
2825 * or bootParameter)
2826 */
2827 #define _MAX_ATTR_ETHBOOTP 2
2828 static int
modify_ethers_bootp(const char * service,const char * rdn,const char * fulldn,const ns_ldap_attr_t * const * attrlist,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)2829 modify_ethers_bootp(
2830 const char *service,
2831 const char *rdn,
2832 const char *fulldn,
2833 const ns_ldap_attr_t * const *attrlist,
2834 const ns_cred_t *cred,
2835 const int flags,
2836 ns_ldap_error_t **errorp)
2837 {
2838 char filter[BUFSIZ];
2839 ns_ldap_result_t *resultp;
2840 int rc = 0;
2841 int i;
2842 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2843 ns_ldap_attr_t new_attrlist0;
2844 char *new_attrvalue0[1];
2845 const ns_ldap_attr_t * const *aptr = attrlist;
2846 ns_ldap_attr_t *aptr2;
2847 ns_ldap_error_t *new_errorp = NULL;
2848
2849 if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2850 errorp == NULL || service == NULL)
2851 return (NS_LDAP_OP_FAILED);
2852
2853 bzero(&new_attrlist, sizeof (new_attrlist));
2854 bzero(&new_attrlist0, sizeof (new_attrlist0));
2855 new_attrlist[0] = &new_attrlist0;
2856 new_attrlist[0]->attrvalue = new_attrvalue0;
2857
2858 new_attrlist[0]->attrname = "objectclass";
2859 new_attrlist[0]->value_count = 1;
2860 if (strcasecmp(service, "ethers") == NULL) {
2861 (void) snprintf(&filter[0], sizeof (filter),
2862 "(&(objectClass=ieee802Device)(%s))", rdn);
2863 new_attrlist[0]->attrvalue[0] = "ieee802Device";
2864 } else {
2865 (void) snprintf(&filter[0], sizeof (filter),
2866 "(&(objectClass=bootableDevice)(%s))", rdn);
2867 new_attrlist[0]->attrvalue[0] = "bootableDevice";
2868 }
2869
2870 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2871 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2872 NULL, NULL);
2873
2874 switch (rc) {
2875 case NS_LDAP_SUCCESS:
2876 /*
2877 * entry already exists for this service
2878 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2879 */
2880 rc = NS_LDAP_INTERNAL;
2881 break;
2882 case NS_LDAP_NOTFOUND:
2883 /*
2884 * entry not found with the given objectclasss but entry exists
2885 * hence add the relevant attribute (macAddress or bootparams).
2886 */
2887 i = 1;
2888 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2889 /* aptr2 needed here to avoid lint warning */
2890 aptr2 = (ns_ldap_attr_t *)*aptr++;
2891 if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2892 (strcasecmp(aptr2->attrname,
2893 "objectclass") != 0)) {
2894 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
2895 }
2896 }
2897
2898 if (i != _MAX_ATTR_ETHBOOTP) {
2899 /* we haven't found all expected attributes */
2900 rc = NS_LDAP_OP_FAILED;
2901 break;
2902 }
2903
2904 aptr = (const ns_ldap_attr_t * const *) new_attrlist;
2905 /* clean errorp first */
2906 (void) __ns_ldap_freeError(errorp);
2907 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2908 errorp);
2909 break;
2910 default:
2911 /*
2912 * unexpected error happenned
2913 * returning relevant error
2914 */
2915 (void) __ns_ldap_freeError(errorp);
2916 *errorp = new_errorp;
2917 break;
2918 }
2919
2920 return (rc);
2921 }
2922
2923 /*
2924 * Conversion: publickey
2925 * Input format: struct _ns_pubkey
2926 * Exported objectclass: NisKeyObject
2927 */
2928 static int
__s_cvt_publickey(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2929 __s_cvt_publickey(const void *data, char **rdn,
2930 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2931 {
2932 ns_ldap_entry_t *e;
2933 int rc;
2934 char trdn[RDNSIZE];
2935 /* routine specific */
2936 struct _ns_pubkey *ptr;
2937 int max_attr = 3;
2938 static char *oclist[] = {
2939 "NisKeyObject",
2940 NULL
2941 };
2942
2943 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2944 return (NS_LDAP_OP_FAILED);
2945 *entry = e = __s_mk_entry(oclist, max_attr);
2946 if (e == NULL)
2947 return (NS_LDAP_MEMORY);
2948
2949 /* Convert the structure */
2950 ptr = (struct _ns_pubkey *)data;
2951
2952 if (ptr->name == NULL || ptr->pubkey == '\0' || ptr->privkey == '\0') {
2953 __ns_ldap_freeEntry(e);
2954 *entry = NULL;
2955 return (NS_LDAP_INVALID_PARAM);
2956 }
2957
2958 /* Create an appropriate rdn */
2959 if (ptr->hostcred == NS_HOSTCRED_FALSE)
2960 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2961 else
2962 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2963 *rdn = strdup(trdn);
2964 if (*rdn == NULL) {
2965 __ns_ldap_freeEntry(e);
2966 *entry = NULL;
2967 return (NS_LDAP_MEMORY);
2968 }
2969
2970 /* Error check the data and add the attributes */
2971
2972 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2973 if (rc != NS_LDAP_SUCCESS) {
2974 __s_cvt_freeEntryRdn(entry, rdn);
2975 return (rc);
2976 }
2977
2978 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2979 if (rc != NS_LDAP_SUCCESS) {
2980 __s_cvt_freeEntryRdn(entry, rdn);
2981 return (rc);
2982 }
2983
2984 return (NS_LDAP_SUCCESS);
2985 }
2986 /*
2987 * Conversion: aliases
2988 * Input format: struct _ns_alias
2989 * Exported objectclass: mailGroup
2990 */
2991 static int
__s_cvt_aliases(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2992 __s_cvt_aliases(const void *data, char **rdn,
2993 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2994 {
2995 ns_ldap_entry_t *e;
2996 int rc;
2997 char trdn[RDNSIZE];
2998 /* routine specific */
2999 struct _ns_alias *ptr;
3000 int max_attr = 4;
3001 int i, j;
3002 char **nm;
3003 static char *oclist[] = {
3004 "mailGroup",
3005 "top",
3006 NULL
3007 };
3008
3009 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3010 return (NS_LDAP_OP_FAILED);
3011 *entry = e = __s_mk_entry(oclist, max_attr);
3012 if (e == NULL)
3013 return (NS_LDAP_MEMORY);
3014
3015 /* Convert the structure */
3016 ptr = (struct _ns_alias *)data;
3017
3018 if (ptr->alias == NULL) {
3019 __ns_ldap_freeEntry(e);
3020 *entry = NULL;
3021 return (NS_LDAP_INVALID_PARAM);
3022 }
3023
3024 /* Create an appropriate rdn */
3025 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
3026 *rdn = strdup(trdn);
3027 if (*rdn == NULL) {
3028 __ns_ldap_freeEntry(e);
3029 *entry = NULL;
3030 return (NS_LDAP_MEMORY);
3031 }
3032
3033 if (ptr->alias != '\0') {
3034 rc = __s_add_attr(e, "mail", (char *)ptr->alias);
3035 if (rc != NS_LDAP_SUCCESS) {
3036 __s_cvt_freeEntryRdn(entry, rdn);
3037 return (rc);
3038 }
3039 }
3040
3041 /* Error check the data and add the attributes */
3042 if (ptr->member && ptr->member[0]) {
3043 nm = ptr->member;
3044 for (i = 0; *nm; i++, nm++)
3045 ;
3046 nm = (char **)calloc(i+2, sizeof (char *));
3047 if (nm == NULL) {
3048 __s_cvt_freeEntryRdn(entry, rdn);
3049 return (NS_LDAP_MEMORY);
3050 }
3051 for (j = 0; j < i; j++)
3052 nm[j] = ptr->member[j];
3053
3054 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
3055 free(nm);
3056 nm = NULL;
3057 if (rc != NS_LDAP_SUCCESS) {
3058 __s_cvt_freeEntryRdn(entry, rdn);
3059 return (rc);
3060 }
3061 }
3062
3063 return (NS_LDAP_SUCCESS);
3064
3065 }
3066 /*
3067 * Conversion: automount
3068 * Input format: struct _ns_automount
3069 * Exported objectclass: automount
3070 */
3071 static int
__s_cvt_auto_mount(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3072 __s_cvt_auto_mount(const void *data, char **rdn,
3073 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3074 {
3075 ns_ldap_entry_t *e;
3076 int rc;
3077 char trdn[RDNSIZE];
3078 /* routine specific */
3079 struct _ns_automount *ptr;
3080 int max_attr = 6;
3081 void **paramVal = NULL;
3082 char **mappedschema = NULL;
3083 int version1 = 0;
3084 static char *oclist[] = {
3085 NULL,
3086 "top",
3087 NULL
3088 };
3089
3090 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3091 return (NS_LDAP_OP_FAILED);
3092
3093 /* determine profile version number */
3094 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp);
3095 if (paramVal && *paramVal &&
3096 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
3097 version1 = 1;
3098 if (paramVal)
3099 (void) __ns_ldap_freeParam(¶mVal);
3100 if (rc && errorp)
3101 (void) __ns_ldap_freeError(errorp);
3102
3103 /* use old schema for version 1 profiles */
3104 if (version1)
3105 oclist[0] = "nisObject";
3106 else
3107 oclist[0] = "automount";
3108
3109 *entry = e = __s_mk_entry(oclist, max_attr);
3110 if (e == NULL)
3111 return (NS_LDAP_MEMORY);
3112
3113 /* Convert the structure */
3114 ptr = (struct _ns_automount *)data;
3115
3116 if (ptr->key == NULL || ptr->value == '\0' || ptr->mapname == '\0') {
3117 __ns_ldap_freeEntry(e);
3118 *entry = NULL;
3119 return (NS_LDAP_INVALID_PARAM);
3120 }
3121
3122 /* Create an appropriate rdn */
3123 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
3124 ptr->key);
3125 *rdn = strdup(trdn);
3126 if (*rdn == NULL) {
3127 __ns_ldap_freeEntry(e);
3128 *entry = NULL;
3129 return (NS_LDAP_MEMORY);
3130 }
3131
3132 if (ptr->key != '\0') {
3133 rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
3134 (char *)ptr->key);
3135 if (rc != NS_LDAP_SUCCESS) {
3136 __s_cvt_freeEntryRdn(entry, rdn);
3137 return (rc);
3138 }
3139 }
3140
3141 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
3142 (char *)ptr->value);
3143 if (rc != NS_LDAP_SUCCESS) {
3144 __s_cvt_freeEntryRdn(entry, rdn);
3145 return (rc);
3146 }
3147
3148 /*
3149 * even for version 2, if automount is mapped to nisObject we
3150 * still need 'nisMapName' attribute
3151 */
3152 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
3153 if (mappedschema && mappedschema[0] &&
3154 strcasecmp(mappedschema[0], "nisObject") == 0)
3155 version1 = 1;
3156 if (mappedschema)
3157 __s_api_free2dArray(mappedschema);
3158
3159 if (version1) {
3160 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
3161 if (rc != NS_LDAP_SUCCESS) {
3162 __s_cvt_freeEntryRdn(entry, rdn);
3163 return (rc);
3164 }
3165 }
3166
3167 return (NS_LDAP_SUCCESS);
3168 }
3169 /*
3170 * Conversion: auth_attr
3171 * Input format: authstr_t
3172 * Exported objectclass: SolarisAuthAttr
3173 */
3174 static int
__s_cvt_authattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3175 __s_cvt_authattr(const void *data, char **rdn,
3176 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3177 {
3178 ns_ldap_entry_t *e;
3179 int rc;
3180 char trdn[RDNSIZE];
3181 /* routine specific */
3182 authstr_t *ptr;
3183 int max_attr = 6;
3184 static char *oclist[] = {
3185 "SolarisAuthAttr",
3186 "top",
3187 NULL
3188 };
3189
3190 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3191 return (NS_LDAP_OP_FAILED);
3192
3193 *entry = e = __s_mk_entry(oclist, max_attr);
3194 if (e == NULL)
3195 return (NS_LDAP_MEMORY);
3196
3197 /* Convert the structure */
3198 ptr = (authstr_t *)data;
3199
3200 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3201 __ns_ldap_freeEntry(e);
3202 *entry = NULL;
3203 return (NS_LDAP_INVALID_PARAM);
3204 }
3205
3206 /* Create an appropriate rdn */
3207 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3208 *rdn = strdup(trdn);
3209 if (*rdn == NULL) {
3210 __ns_ldap_freeEntry(e);
3211 *entry = NULL;
3212 return (NS_LDAP_MEMORY);
3213 }
3214
3215 rc = __s_add_attr(e, "cn", ptr->name);
3216 if (rc != NS_LDAP_SUCCESS) {
3217 __s_cvt_freeEntryRdn(entry, rdn);
3218 return (rc);
3219 }
3220
3221 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3222 if (rc != NS_LDAP_SUCCESS) {
3223 __s_cvt_freeEntryRdn(entry, rdn);
3224 return (rc);
3225 }
3226
3227 if (ptr->res1 != NULL) {
3228 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3229 if (rc != NS_LDAP_SUCCESS) {
3230 __s_cvt_freeEntryRdn(entry, rdn);
3231 return (rc);
3232 }
3233 }
3234
3235 if (ptr->res2 != NULL) {
3236 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3237 if (rc != NS_LDAP_SUCCESS) {
3238 __s_cvt_freeEntryRdn(entry, rdn);
3239 return (rc);
3240 }
3241 }
3242
3243 if (ptr->short_desc != NULL) {
3244 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
3245 if (rc != NS_LDAP_SUCCESS) {
3246 __s_cvt_freeEntryRdn(entry, rdn);
3247 return (rc);
3248 }
3249 }
3250
3251 if (ptr->long_desc != NULL) {
3252 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
3253 if (rc != NS_LDAP_SUCCESS) {
3254 __s_cvt_freeEntryRdn(entry, rdn);
3255 return (rc);
3256 }
3257 }
3258
3259 return (NS_LDAP_SUCCESS);
3260 }
3261 /*
3262 * Conversion: exec_attr
3263 * Input format: execstr_t
3264 * Exported objectclass: SolarisExecAttr
3265 */
3266 static int
__s_cvt_execattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3267 __s_cvt_execattr(const void *data, char **rdn,
3268 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3269 {
3270 ns_ldap_entry_t *e;
3271 int rc;
3272 char trdn[RDNSIZE];
3273 char esc_str[RDNSIZE];
3274 /* routine specific */
3275 execstr_t *ptr;
3276 int max_attr = 7;
3277 static char *oclist[] = {
3278 "SolarisExecAttr",
3279 "SolarisProfAttr",
3280 "top",
3281 NULL
3282 };
3283
3284 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3285 return (NS_LDAP_OP_FAILED);
3286
3287 *entry = e = __s_mk_entry(oclist, max_attr);
3288 if (e == NULL)
3289 return (NS_LDAP_MEMORY);
3290
3291 /* Convert the structure */
3292 ptr = (execstr_t *)data;
3293
3294 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3295 ptr->policy == NULL || ptr->policy[0] == '\0' ||
3296 ptr->type == NULL || ptr->type[0] == '\0' ||
3297 ptr->id == NULL || ptr->id[0] == '\0') {
3298 __ns_ldap_freeEntry(e);
3299 *entry = NULL;
3300 return (NS_LDAP_INVALID_PARAM);
3301 }
3302
3303 /*
3304 * Escape special characters in ProfileID.
3305 */
3306 if (escape_str(esc_str, ptr->id) != 0) {
3307 __ns_ldap_freeEntry(e);
3308 *entry = NULL;
3309 return (NS_LDAP_INVALID_PARAM);
3310 }
3311
3312 /* Create an appropriate rdn */
3313 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
3314 "+SolarisProfileType=%s+SolarisProfileId=%s",
3315 ptr->name, ptr->policy, ptr->type, esc_str);
3316
3317 *rdn = strdup(trdn);
3318 if (*rdn == NULL) {
3319 __ns_ldap_freeEntry(e);
3320 *entry = NULL;
3321 return (NS_LDAP_MEMORY);
3322 }
3323
3324 rc = __s_add_attr(e, "cn", ptr->name);
3325 if (rc != NS_LDAP_SUCCESS) {
3326 __s_cvt_freeEntryRdn(entry, rdn);
3327 return (rc);
3328 }
3329
3330 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
3331 if (rc != NS_LDAP_SUCCESS) {
3332 __s_cvt_freeEntryRdn(entry, rdn);
3333 return (rc);
3334 }
3335
3336 rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
3337 if (rc != NS_LDAP_SUCCESS) {
3338 __s_cvt_freeEntryRdn(entry, rdn);
3339 return (rc);
3340 }
3341
3342 rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
3343 if (rc != NS_LDAP_SUCCESS) {
3344 __s_cvt_freeEntryRdn(entry, rdn);
3345 return (rc);
3346 }
3347
3348 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3349 if (rc != NS_LDAP_SUCCESS) {
3350 __s_cvt_freeEntryRdn(entry, rdn);
3351 return (rc);
3352 }
3353
3354 if (ptr->res1 != NULL) {
3355 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
3356 if (rc != NS_LDAP_SUCCESS) {
3357 __s_cvt_freeEntryRdn(entry, rdn);
3358 return (rc);
3359 }
3360 }
3361
3362 if (ptr->res2 != NULL) {
3363 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
3364 if (rc != NS_LDAP_SUCCESS) {
3365 __s_cvt_freeEntryRdn(entry, rdn);
3366 return (rc);
3367 }
3368 }
3369
3370 return (NS_LDAP_SUCCESS);
3371 }
3372 /*
3373 * Conversion: prof_attr
3374 * Input format: profstr_t
3375 * Exported objectclass: SolarisProfAttr
3376 */
3377 static int
__s_cvt_profattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3378 __s_cvt_profattr(const void *data, char **rdn,
3379 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3380 {
3381 ns_ldap_entry_t *e;
3382 int rc;
3383 char trdn[RDNSIZE];
3384 /* routine specific */
3385 profstr_t *ptr;
3386 int max_attr = 5;
3387 static char *oclist[] = {
3388 "SolarisProfAttr",
3389 "top",
3390 NULL
3391 };
3392
3393 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3394 return (NS_LDAP_OP_FAILED);
3395
3396 *entry = e = __s_mk_entry(oclist, max_attr);
3397 if (e == NULL)
3398 return (NS_LDAP_MEMORY);
3399
3400 /* Convert the structure */
3401 ptr = (profstr_t *)data;
3402
3403 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3404 __ns_ldap_freeEntry(e);
3405 *entry = NULL;
3406 return (NS_LDAP_INVALID_PARAM);
3407 }
3408
3409 /* Create an appropriate rdn */
3410 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3411 *rdn = strdup(trdn);
3412 if (*rdn == NULL) {
3413 __ns_ldap_freeEntry(e);
3414 *entry = NULL;
3415 return (NS_LDAP_MEMORY);
3416 }
3417
3418 rc = __s_add_attr(e, "cn", ptr->name);
3419 if (rc != NS_LDAP_SUCCESS) {
3420 __s_cvt_freeEntryRdn(entry, rdn);
3421 return (rc);
3422 }
3423
3424 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3425 if (rc != NS_LDAP_SUCCESS) {
3426 __s_cvt_freeEntryRdn(entry, rdn);
3427 return (rc);
3428 }
3429
3430 if (ptr->res1 != NULL) {
3431 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3432 if (rc != NS_LDAP_SUCCESS) {
3433 __s_cvt_freeEntryRdn(entry, rdn);
3434 return (rc);
3435 }
3436 }
3437
3438 if (ptr->res2 != NULL) {
3439 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3440 if (rc != NS_LDAP_SUCCESS) {
3441 __s_cvt_freeEntryRdn(entry, rdn);
3442 return (rc);
3443 }
3444 }
3445
3446 if (ptr->desc != NULL) {
3447 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3448 if (rc != NS_LDAP_SUCCESS) {
3449 __s_cvt_freeEntryRdn(entry, rdn);
3450 return (rc);
3451 }
3452 }
3453
3454 return (NS_LDAP_SUCCESS);
3455 }
3456 /*
3457 * Conversion: user_attr
3458 * Input format: userstr_t
3459 * Exported objectclass: SolarisUserAttr
3460 */
3461 static int
__s_cvt_userattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3462 __s_cvt_userattr(const void *data, char **rdn,
3463 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3464 {
3465 ns_ldap_entry_t *e;
3466 int rc;
3467 char trdn[RDNSIZE];
3468 /* routine specific */
3469 userstr_t *ptr;
3470 int max_attr = 5;
3471 static char *oclist[] = {
3472 "SolarisUserAttr",
3473 NULL
3474 };
3475
3476 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3477 return (NS_LDAP_OP_FAILED);
3478
3479 *entry = e = __s_mk_entry(oclist, max_attr);
3480 if (e == NULL)
3481 return (NS_LDAP_MEMORY);
3482
3483 /* Convert the structure */
3484 ptr = (userstr_t *)data;
3485
3486 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3487 ptr->attr == NULL) {
3488 __ns_ldap_freeEntry(e);
3489 *entry = NULL;
3490 return (NS_LDAP_INVALID_PARAM);
3491 }
3492
3493 /* Create an appropriate rdn */
3494 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3495 *rdn = strdup(trdn);
3496 if (*rdn == NULL) {
3497 __ns_ldap_freeEntry(e);
3498 *entry = NULL;
3499 return (NS_LDAP_MEMORY);
3500 }
3501
3502 /*
3503 * SolarisUserAttr has no uid attribute
3504 */
3505
3506 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3507 if (rc != NS_LDAP_SUCCESS) {
3508 __s_cvt_freeEntryRdn(entry, rdn);
3509 return (rc);
3510 }
3511
3512 if (ptr->qualifier != NULL) {
3513 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3514 if (rc != NS_LDAP_SUCCESS) {
3515 __s_cvt_freeEntryRdn(entry, rdn);
3516 return (rc);
3517 }
3518 }
3519
3520 if (ptr->res1 != NULL) {
3521 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3522 if (rc != NS_LDAP_SUCCESS) {
3523 __s_cvt_freeEntryRdn(entry, rdn);
3524 return (rc);
3525 }
3526 }
3527
3528 if (ptr->res2 != NULL) {
3529 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3530 if (rc != NS_LDAP_SUCCESS) {
3531 __s_cvt_freeEntryRdn(entry, rdn);
3532 return (rc);
3533 }
3534 }
3535
3536 return (NS_LDAP_SUCCESS);
3537 }
3538 /*
3539 * Conversion: audit_user
3540 * Input format: au_user_str_t
3541 * Exported objectclass: SolarisAuditUser
3542 */
3543 static int
__s_cvt_audituser(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3544 __s_cvt_audituser(const void *data, char **rdn,
3545 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3546 {
3547 ns_ldap_entry_t *e;
3548 int rc;
3549 char trdn[RDNSIZE];
3550 /* routine specific */
3551 au_user_str_t *ptr;
3552 int max_attr = 3;
3553 static char *oclist[] = {
3554 "SolarisAuditUser",
3555 NULL
3556 };
3557
3558 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3559 return (NS_LDAP_OP_FAILED);
3560
3561 *entry = e = __s_mk_entry(oclist, max_attr);
3562 if (e == NULL)
3563 return (NS_LDAP_MEMORY);
3564
3565 /* Convert the structure */
3566 ptr = (au_user_str_t *)data;
3567
3568 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
3569 __ns_ldap_freeEntry(e);
3570 *entry = NULL;
3571 return (NS_LDAP_INVALID_PARAM);
3572 }
3573
3574 /* Create an appropriate rdn */
3575 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
3576 *rdn = strdup(trdn);
3577 if (*rdn == NULL) {
3578 __ns_ldap_freeEntry(e);
3579 *entry = NULL;
3580 return (NS_LDAP_MEMORY);
3581 }
3582
3583 /*
3584 * Solaris AuditUser has no uid attribute
3585 */
3586
3587 if (ptr->au_always != NULL) {
3588 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
3589 if (rc != NS_LDAP_SUCCESS) {
3590 __s_cvt_freeEntryRdn(entry, rdn);
3591 return (rc);
3592 }
3593 }
3594
3595 if (ptr->au_never != NULL) {
3596 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
3597 if (rc != NS_LDAP_SUCCESS) {
3598 __s_cvt_freeEntryRdn(entry, rdn);
3599 return (rc);
3600 }
3601 }
3602
3603 return (NS_LDAP_SUCCESS);
3604 }
3605 /*
3606 * Conversion: tnrhtp
3607 * Input format: tsol_tpstr_t
3608 * Exported objectclass: ipTnetTemplate
3609 */
3610 static int
__s_cvt_tnrhtp(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3611 __s_cvt_tnrhtp(const void *data, char **rdn,
3612 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3613 {
3614 ns_ldap_entry_t *e;
3615 int rc;
3616 char trdn[RDNSIZE];
3617 char esc_str[RDNSIZE];
3618 /* routine specific */
3619 int max_attr = 2;
3620 tsol_tpstr_t *ptr;
3621 static char *oclist[] = {
3622 "ipTnetTemplate",
3623 "top",
3624 NULL
3625 };
3626
3627 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3628 return (NS_LDAP_OP_FAILED);
3629
3630 *entry = e = __s_mk_entry(oclist, max_attr);
3631 if (e == NULL)
3632 return (NS_LDAP_MEMORY);
3633
3634 /* Convert the structure */
3635 ptr = (tsol_tpstr_t *)data;
3636
3637 if (ptr->template == NULL || *ptr->template == '\0') {
3638 __ns_ldap_freeEntry(e);
3639 *entry = NULL;
3640 return (NS_LDAP_INVALID_PARAM);
3641 }
3642
3643 /*
3644 * Escape special characters in Template name.
3645 */
3646 if (escape_str(esc_str, ptr->template) != 0) {
3647 __ns_ldap_freeEntry(e);
3648 *entry = NULL;
3649 return (NS_LDAP_INVALID_PARAM);
3650 }
3651
3652 /* Create an appropriate rdn */
3653 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str);
3654 *rdn = strdup(trdn);
3655 if (*rdn == NULL) {
3656 __ns_ldap_freeEntry(e);
3657 *entry = NULL;
3658 return (NS_LDAP_MEMORY);
3659 }
3660
3661 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3662 if (rc != NS_LDAP_SUCCESS) {
3663 __s_cvt_freeEntryRdn(entry, rdn);
3664 return (rc);
3665 }
3666
3667 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs);
3668 if (rc != NS_LDAP_SUCCESS) {
3669 __s_cvt_freeEntryRdn(entry, rdn);
3670 return (rc);
3671 }
3672
3673 return (NS_LDAP_SUCCESS);
3674 }
3675 /*
3676 * Conversion: tnrhdb
3677 * Input format: tsol_rhstr_t
3678 * Exported objectclass: ipTnetHost
3679 */
3680 static int
__s_cvt_tnrhdb(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3681 __s_cvt_tnrhdb(const void *data, char **rdn,
3682 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3683 {
3684 ns_ldap_entry_t *e;
3685 int rc;
3686 char trdn[RDNSIZE];
3687 /* routine specific */
3688 tsol_rhstr_t *ptr;
3689 int max_attr = 2;
3690 static char *oclist[] = {
3691 "ipTnetHost",
3692 "ipTnetTemplate",
3693 "top",
3694 NULL
3695 };
3696
3697 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3698 return (NS_LDAP_OP_FAILED);
3699
3700 *entry = e = __s_mk_entry(oclist, max_attr);
3701 if (e == NULL)
3702 return (NS_LDAP_MEMORY);
3703
3704 /* Convert the structure */
3705 ptr = (tsol_rhstr_t *)data;
3706
3707 if (ptr->address == NULL || *ptr->address == '\0' ||
3708 ptr->template == NULL || *ptr->template == '\0') {
3709 __ns_ldap_freeEntry(e);
3710 *entry = NULL;
3711 return (NS_LDAP_INVALID_PARAM);
3712 }
3713
3714 /* Create an appropriate rdn */
3715 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address);
3716 *rdn = strdup(trdn);
3717 if (*rdn == NULL) {
3718 __ns_ldap_freeEntry(e);
3719 *entry = NULL;
3720 return (NS_LDAP_MEMORY);
3721 }
3722
3723 rc = __s_add_attr(e, "ipTnetNumber", ptr->address);
3724 if (rc != NS_LDAP_SUCCESS) {
3725 __s_cvt_freeEntryRdn(entry, rdn);
3726 return (rc);
3727 }
3728
3729 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3730 if (rc != NS_LDAP_SUCCESS) {
3731 __s_cvt_freeEntryRdn(entry, rdn);
3732 return (rc);
3733 }
3734
3735 return (NS_LDAP_SUCCESS);
3736 }
3737 /*
3738 * Add Typed Entry Conversion data structures
3739 */
3740
3741 typedef struct __ns_cvt_type {
3742 const char *service;
3743 int flags;
3744 #define AE 1 /* alway add entries */
3745 int (*cvt_rtn)(const void *data,
3746 char **rdn,
3747 ns_ldap_entry_t **entry,
3748 ns_ldap_error_t **errorp);
3749 } __ns_cvt_type_t;
3750
3751 static __ns_cvt_type_t __s_cvtlist[] = {
3752 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd },
3753 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group },
3754 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts },
3755 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts },
3756 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc },
3757 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols },
3758 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks },
3759 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups },
3760 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases },
3761 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services },
3762 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers },
3763 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow },
3764 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks },
3765 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams },
3766 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr },
3767 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr },
3768 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr },
3769 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr },
3770 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
3771 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
3772 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser },
3773 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp },
3774 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb },
3775 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project },
3776 { NULL, 0, NULL },
3777 };
3778
3779 /*
3780 * Add Typed Entry Routine
3781 */
3782
3783 /*ARGSUSED*/
__ns_ldap_addTypedEntry(const char * servicetype,const char * basedn,const void * data,const int create,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)3784 int __ns_ldap_addTypedEntry(
3785 const char *servicetype,
3786 const char *basedn,
3787 const void *data,
3788 const int create,
3789 const ns_cred_t *cred,
3790 const int flags,
3791 ns_ldap_error_t **errorp)
3792 {
3793 char *rdn = NULL, *fulldn = NULL;
3794 void **paramVal = NULL;
3795 ns_ldap_entry_t *entry = NULL;
3796 const ns_ldap_attr_t *const *modattrlist;
3797 ns_ldap_search_desc_t **sdlist;
3798 char **dns = NULL;
3799 char trdn[RDNSIZE];
3800 char service[BUFSIZE];
3801 int rc = 0;
3802 int automount = 0;
3803 int i, s;
3804
3805 rc = NS_LDAP_OP_FAILED;
3806 for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3807 if (__s_cvtlist[s].cvt_rtn == NULL)
3808 continue;
3809 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3810 break;
3811 /* Or, check if the servicetype is auto_ */
3812 if (strcmp(__s_cvtlist[s].service,
3813 NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3814 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3815 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3816 automount++;
3817 break;
3818 }
3819 }
3820 if (__s_cvtlist[s].service == NULL)
3821 return (rc);
3822
3823 /* Convert the data */
3824 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3825 if (rc != NS_LDAP_SUCCESS) {
3826 __s_cvt_freeEntryRdn(&entry, &rdn);
3827 return (rc);
3828 }
3829 if (rdn == NULL) {
3830 __ns_ldap_freeEntry(entry);
3831 return (NS_LDAP_OP_FAILED);
3832 }
3833
3834 if (strcmp(servicetype, "publickey") == 0) {
3835 struct _ns_pubkey *ptr;
3836 ptr = (struct _ns_pubkey *)data;
3837 if (ptr->hostcred == NS_HOSTCRED_TRUE)
3838 (void) strcpy(service, "hosts");
3839 else
3840 (void) strcpy(service, "passwd");
3841 } else
3842 (void) strcpy(service, servicetype);
3843
3844 /* Create the Full DN */
3845 if (basedn == NULL) {
3846 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3847 &sdlist, errorp);
3848 if (rc != NS_LDAP_SUCCESS) {
3849 __s_cvt_freeEntryRdn(&entry, &rdn);
3850 return (rc);
3851 }
3852
3853 if (sdlist == NULL) {
3854 rc = __s_api_getDNs(&dns, service, errorp);
3855 if (rc != NS_LDAP_SUCCESS) {
3856 if (dns) {
3857 __s_api_free2dArray(dns);
3858 dns = NULL;
3859 }
3860 __s_cvt_freeEntryRdn(&entry, &rdn);
3861 return (rc);
3862 }
3863 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3864 __s_api_free2dArray(dns);
3865 } else {
3866 if (sdlist[0]->basedn) {
3867 (void) snprintf(trdn, RDNSIZE, "%s,%s",
3868 rdn, sdlist[0]->basedn);
3869 } else {
3870 __s_cvt_freeEntryRdn(&entry, &rdn);
3871 return (NS_LDAP_OP_FAILED);
3872 }
3873 }
3874 i = strlen(trdn) - 1;
3875 if (trdn[i] == COMMATOK) {
3876 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3877 ¶mVal, errorp);
3878 if (rc != NS_LDAP_SUCCESS) {
3879 __s_cvt_freeEntryRdn(&entry, &rdn);
3880 return (rc);
3881 }
3882 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3883 fulldn = (char *)calloc(i, 1);
3884 if (fulldn == NULL) {
3885 (void) __ns_ldap_freeParam(¶mVal);
3886 __s_cvt_freeEntryRdn(&entry, &rdn);
3887 return (NS_LDAP_MEMORY);
3888 }
3889 (void) snprintf(fulldn, i, "%s%s", trdn,
3890 (char *)(paramVal[0]));
3891 (void) __ns_ldap_freeParam(¶mVal);
3892 } else {
3893 fulldn = strdup(trdn);
3894 if (fulldn == NULL) {
3895 __s_cvt_freeEntryRdn(&entry, &rdn);
3896 return (NS_LDAP_MEMORY);
3897 }
3898 }
3899 } else {
3900 i = strlen(rdn) + strlen(basedn) + 2;
3901 fulldn = (char *)calloc(i, 1);
3902 if (fulldn == NULL) {
3903 __s_cvt_freeEntryRdn(&entry, &rdn);
3904 return (NS_LDAP_MEMORY);
3905 }
3906 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3907 }
3908
3909 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3910 /* Check to see if the entry exists already */
3911 /* May need to delete or update first */
3912
3913 if (create != 1) {
3914 /* Modify the entry */
3915 /*
3916 * To add a shadow-like entry, the addTypedEntry function
3917 * would call __ns_ldap_repAttr first, and if server says
3918 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
3919 * This is to allow a netmask entry to be added even if the
3920 * base network entry is not in the directory. It would work
3921 * because the difference between the schema for the network
3922 * and netmask data contains only MAY attributes.
3923 *
3924 * But for shadow data, the attributes do not have MUST
3925 * attributes the base entry needs, so if the __ns_ldap_addEntry
3926 * is executed, it would fail. The real reason, however, is that
3927 * the base entry did not exist. So returning
3928 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
3929 */
3930 if ((__s_cvtlist[s].flags & AE) != 0)
3931 rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3932 cred, flags, errorp);
3933 else {
3934 rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3935 cred, flags, errorp);
3936 if (rc == NS_LDAP_INTERNAL && *errorp &&
3937 (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3938 (void) __ns_ldap_freeError(errorp);
3939 rc = __ns_ldap_addEntry(service, fulldn,
3940 entry, cred, flags, errorp);
3941 if (rc == NS_LDAP_INTERNAL && *errorp &&
3942 (*errorp)->status ==
3943 LDAP_OBJECT_CLASS_VIOLATION)
3944 (*errorp)->status = LDAP_NO_SUCH_OBJECT;
3945 }
3946 }
3947 } else {
3948 /* Add the entry */
3949 rc = __ns_ldap_addEntry(service, fulldn, entry,
3950 cred, flags, errorp);
3951 if (rc == NS_LDAP_INTERNAL && *errorp &&
3952 (*errorp)->status == LDAP_ALREADY_EXISTS &&
3953 ((strcmp(service, "ethers") == 0) ||
3954 (strcmp(service, "bootparams") == 0))) {
3955 rc = modify_ethers_bootp(service, rdn, fulldn,
3956 modattrlist, cred, flags, errorp);
3957 }
3958 }
3959
3960 /* Free up entry created by conversion routine */
3961 if (fulldn != NULL)
3962 free(fulldn);
3963 __s_cvt_freeEntryRdn(&entry, &rdn);
3964 return (rc);
3965 }
3966
3967
3968 /*
3969 * Append the default base dn to the dn
3970 * when it ends with ','.
3971 * e.g.
3972 * SSD = service:ou=foo,
3973 */
3974 int
__s_api_append_default_basedn(const char * dn,char ** new_dn,int * allocated,ns_ldap_error_t ** errp)3975 __s_api_append_default_basedn(
3976 const char *dn,
3977 char **new_dn,
3978 int *allocated,
3979 ns_ldap_error_t **errp) {
3980
3981 int rc = NS_LDAP_SUCCESS, len = 0;
3982 void **param = NULL;
3983 char *str = NULL;
3984
3985 *allocated = FALSE;
3986 *new_dn = NULL;
3987
3988 if (dn == NULL)
3989 return (NS_LDAP_INVALID_PARAM);
3990
3991 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3992 (void ***)¶m, errp);
3993
3994 if (rc != NS_LDAP_SUCCESS) {
3995 if (param)
3996 (void) __ns_ldap_freeParam(¶m);
3997 return (rc);
3998 }
3999
4000 len = strlen(dn);
4001 str = ((char **)param)[0];
4002 len = len + strlen(str) +1;
4003 *new_dn = (char *)malloc(len);
4004 if (*new_dn == NULL) {
4005 (void) __ns_ldap_freeParam(¶m);
4006 return (NS_LDAP_MEMORY);
4007 }
4008 *allocated = TRUE;
4009
4010 (void) strcpy(*new_dn, dn);
4011 (void) strcat(*new_dn, str);
4012
4013 (void) __ns_ldap_freeParam(¶m);
4014 return (NS_LDAP_SUCCESS);
4015 }
4016
4017 /*
4018 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
4019 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
4020 * The output contains a count, a list of offsets, which show where the
4021 * corresponding copied attribute type and attribute value are located.
4022 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
4023 * the output is the ldap_strlist_t structure with: ldap_count = 6,
4024 * (buf + ldap_offsets[0]) -> "dn"
4025 * (buf + ldap_offsets[1]) -> "aaaa"
4026 * (buf + ldap_offsets[2]) -> "userPassword"
4027 * (buf + ldap_offsets[3]) -> "bbbb"
4028 * (buf + ldap_offsets[4]) -> "shadowlastchange"
4029 * (buf + ldap_offsets[5]) -> "cccc"
4030 * and all the string data shown above copied into the buffer after
4031 * the offset array. The total length of the data will be the return
4032 * value, or -1 if error.
4033 */
4034 static int
attr2list(const char * dn,ns_ldap_attr_t ** attr,char * buf,int bufsize)4035 attr2list(const char *dn, ns_ldap_attr_t **attr,
4036 char *buf, int bufsize)
4037 {
4038 int c = 0;
4039 char *ap;
4040 int ao;
4041 ldap_strlist_t *al = (ldap_strlist_t *)buf;
4042 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
4043 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
4044
4045 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
4046 if ((strlen(dn) + 2 + 1) >= bufsize)
4047 return (-1);
4048
4049 /* count number of attributes */
4050 while (*aptr++)
4051 c++;
4052 al->ldap_count = 2 + c * 2;
4053 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
4054 al->ldap_count;
4055 if (ao > bufsize)
4056 return (-1);
4057 al->ldap_offsets[0] = ao;
4058 ap = buf + ao;
4059 ao += 3;
4060
4061 /* copy entry DN */
4062 if (ao > bufsize)
4063 return (-1);
4064 (void) strlcpy(ap, "dn", bufsize);
4065 ap += 3;
4066
4067 al->ldap_offsets[1] = ao;
4068 ao += strlen(dn) + 1;
4069 if (ao > bufsize)
4070 return (-1);
4071 (void) strlcpy(ap, dn, bufsize);
4072 ap = buf + ao;
4073
4074 aptr = attr;
4075 for (c = 2; c < al->ldap_count; c++, aptr++) {
4076 a = *aptr;
4077 if (a->attrname == NULL || a->attrvalue == NULL ||
4078 a->value_count != 1 || a->attrvalue[0] == NULL)
4079 return (-1);
4080 al->ldap_offsets[c] = ao;
4081 ao += strlen(a->attrname) + 1;
4082 if (ao > bufsize)
4083 return (-1);
4084 (void) strlcpy(ap, a->attrname, bufsize);
4085 ap = buf + ao;
4086
4087 c++;
4088 al->ldap_offsets[c] = ao;
4089 ao += strlen(a->attrvalue[0]) + 1;
4090 (void) strlcpy(ap, a->attrvalue[0], bufsize);
4091 ap = buf + ao;
4092 };
4093
4094 return (ao);
4095 }
4096
4097 /*
4098 * Send a modify request to the ldap_cachemgr daemon
4099 * which will use the admin credential to perform the
4100 * operation.
4101 */
4102
4103 static int
send_to_cachemgr(const char * dn,ns_ldap_attr_t ** attr,ns_ldap_error_t ** errorp)4104 send_to_cachemgr(
4105 const char *dn,
4106 ns_ldap_attr_t **attr,
4107 ns_ldap_error_t **errorp)
4108 {
4109 union {
4110 ldap_data_t s_d;
4111 char s_b[DOORBUFFERSIZE];
4112 } space;
4113
4114 ldap_data_t *sptr;
4115 int ndata;
4116 int adata;
4117 int len;
4118 int rc;
4119 char errstr[MAXERROR];
4120 ldap_admin_mod_result_t *admin_result;
4121
4122 *errorp = NULL;
4123 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
4124 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
4125 sizeof (space) - offsetof(ldap_return_t, ldap_u));
4126 if (len <= 0)
4127 return (NS_LDAP_INVALID_PARAM);
4128
4129 adata = sizeof (ldap_call_t) + len;
4130 ndata = sizeof (space);
4131 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
4132 sptr = &space.s_d;
4133
4134 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
4135 case NS_CACHE_SUCCESS:
4136 break;
4137 case NS_CACHE_NOTFOUND:
4138 (void) snprintf(errstr, sizeof (errstr),
4139 gettext("Door call ADMINMODIFY to "
4140 "ldap_cachemgr failed - error: %d"),
4141 space.s_d.ldap_ret.ldap_errno);
4142 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
4143 strdup(errstr), NULL);
4144 return (NS_LDAP_OP_FAILED);
4145 break;
4146 default:
4147 return (NS_LDAP_OP_FAILED);
4148 }
4149
4150 admin_result = &sptr->ldap_ret.ldap_u.admin_result;
4151 if (admin_result->ns_err == NS_LDAP_SUCCESS)
4152 rc = NS_LDAP_SUCCESS;
4153 else {
4154 rc = admin_result->ns_err;
4155 if (admin_result->msg_size == 0)
4156 *errorp = __s_api_make_error(admin_result->status,
4157 NULL);
4158 else
4159 *errorp = __s_api_make_error(admin_result->status,
4160 admin_result->msg);
4161 }
4162
4163 /* clean up the door call */
4164 if (sptr != &space.s_d) {
4165 (void) munmap((char *)sptr, ndata);
4166 }
4167
4168 return (rc);
4169 }
4170