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