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, NS_LDAP_MEMORY);
1070 } else {
1071 MKERROR(LOG_INFO, *errorp, Errno, err,
1072 NS_LDAP_MEMORY);
1073 }
1074 if (conn_user != NULL &&
1075 (Errno == LDAP_SERVER_DOWN ||
1076 Errno == LDAP_CONNECT_ERROR)) {
1077 __s_api_conn_mt_close(conn_user, Errno, errorp);
1078 }
1079 return_rc = NS_LDAP_INTERNAL;
1080 new_state = W_EXIT;
1081 break;
1082 case W_ERROR:
1083 default:
1084 (void) sprintf(errstr,
1085 gettext("Internal write State machine exit"
1086 " (state = %d, rc = %d)."),
1087 err_state, return_rc);
1088 err = strdup(errstr);
1089 MKERROR(LOG_WARNING, *errorp, return_rc, err,
1090 NS_LDAP_MEMORY);
1091 new_state = W_EXIT;
1092 break;
1093 }
1094
1095 if (new_state == W_ERROR)
1096 err_state = state;
1097
1098 if (conn_user != NULL && conn_user->bad_mt_conn == B_TRUE) {
1099 __s_api_conn_mt_close(conn_user, 0, NULL);
1100 new_state = W_EXIT;
1101 }
1102
1103 state = new_state;
1104 }
1105
1106 /*
1107 * should never be here, the next line is to eliminating
1108 * lint message
1109 */
1110 return (NS_LDAP_INTERNAL);
1111 }
1112
1113
1114 /*ARGSUSED*/
1115 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)1116 __ns_ldap_addAttr(
1117 const char *service,
1118 const char *dn,
1119 const ns_ldap_attr_t * const *attr,
1120 const ns_cred_t *cred,
1121 const int flags,
1122 ns_ldap_error_t ** errorp)
1123 {
1124 LDAPMod **mods;
1125 int rc = 0;
1126
1127 #ifdef DEBUG
1128 (void) fprintf(stderr, "__ns_ldap_addAttr START\n");
1129 #endif
1130 *errorp = NULL;
1131
1132 /* Sanity check */
1133 if ((attr == NULL) || (*attr == NULL) ||
1134 (dn == NULL) || (cred == NULL))
1135 return (NS_LDAP_INVALID_PARAM);
1136
1137 mods = __s_api_makeModList(service, attr, LDAP_MOD_ADD, flags);
1138 if (mods == NULL) {
1139 return (NS_LDAP_MEMORY);
1140 }
1141
1142 rc = write_state_machine(LDAP_REQ_MODIFY,
1143 (char *)dn, mods, cred, flags, errorp);
1144 freeModList(mods);
1145
1146 return (rc);
1147 }
1148
1149
1150 /*ARGSUSED*/
1151 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)1152 __ns_ldap_delAttr(
1153 const char *service,
1154 const char *dn,
1155 const ns_ldap_attr_t * const *attr,
1156 const ns_cred_t *cred,
1157 const int flags,
1158 ns_ldap_error_t ** errorp)
1159 {
1160 LDAPMod **mods;
1161 int rc = 0;
1162
1163 #ifdef DEBUG
1164 (void) fprintf(stderr, "__ns_ldap_delAttr START\n");
1165 #endif
1166 *errorp = NULL;
1167
1168 /* Sanity check */
1169 if ((attr == NULL) || (*attr == NULL) ||
1170 (dn == NULL) || (cred == NULL))
1171 return (NS_LDAP_INVALID_PARAM);
1172
1173 mods = __s_api_makeModList(service, attr, LDAP_MOD_DELETE, flags);
1174 if (mods == NULL) {
1175 return (NS_LDAP_MEMORY);
1176 }
1177
1178 rc = write_state_machine(LDAP_REQ_MODIFY,
1179 (char *)dn, mods, cred, flags, errorp);
1180
1181 freeModList(mods);
1182 return (rc);
1183 }
1184
1185 /* Retrieve the admin bind password from the configuration, if allowed. */
1186 static int
get_admin_passwd(ns_cred_t * cred,ns_ldap_error_t ** errorp)1187 get_admin_passwd(ns_cred_t *cred, ns_ldap_error_t **errorp)
1188 {
1189 void **paramVal = NULL;
1190 int rc, ldaprc;
1191 char *modparamVal = NULL;
1192
1193 /*
1194 * For GSSAPI/Kerberos, host credential is used, no need to get
1195 * admin bind password
1196 */
1197 if (cred->auth.saslmech == NS_LDAP_SASL_GSSAPI)
1198 return (NS_LDAP_SUCCESS);
1199
1200 /*
1201 * Retrieve admin bind password.
1202 * The admin bind password is available
1203 * only in the ldap_cachemgr process as
1204 * they are not exposed outside of that
1205 * process.
1206 */
1207 paramVal = NULL;
1208 if ((ldaprc = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1209 ¶mVal, errorp)) != NS_LDAP_SUCCESS)
1210 return (ldaprc);
1211 if (paramVal == NULL || *paramVal == NULL) {
1212 rc = NS_LDAP_CONFIG;
1213 *errorp = __s_api_make_error(NS_CONFIG_NODEFAULT,
1214 gettext("Admin bind password not configured"));
1215 if (*errorp == NULL)
1216 rc = NS_LDAP_MEMORY;
1217 return (rc);
1218 }
1219 modparamVal = dvalue((char *)*paramVal);
1220 (void) memset(*paramVal, 0, strlen((char *)*paramVal));
1221 (void) __ns_ldap_freeParam(¶mVal);
1222 if (modparamVal == NULL || *((char *)modparamVal) == '\0') {
1223 if (modparamVal != NULL)
1224 free(modparamVal);
1225 rc = NS_LDAP_CONFIG;
1226 *errorp = __s_api_make_error(NS_CONFIG_SYNTAX,
1227 gettext("bind password not valid"));
1228 if (*errorp == NULL)
1229 rc = NS_LDAP_MEMORY;
1230 return (rc);
1231 }
1232
1233 cred->cred.unix_cred.passwd = modparamVal;
1234 return (NS_LDAP_SUCCESS);
1235 }
1236
1237 boolean_t
__ns_ldap_is_shadow_update_enabled(void)1238 __ns_ldap_is_shadow_update_enabled(void)
1239 {
1240 int **enable_shadow = NULL;
1241 ns_ldap_error_t *errorp = NULL;
1242
1243 if (__ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
1244 (void ***)&enable_shadow, &errorp) != NS_LDAP_SUCCESS) {
1245 if (errorp)
1246 (void) __ns_ldap_freeError(&errorp);
1247 return (B_FALSE);
1248 }
1249 if ((enable_shadow != NULL && *enable_shadow != NULL) &&
1250 (*enable_shadow[0] == NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE)) {
1251 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1252 return (B_TRUE);
1253 }
1254 if (enable_shadow != NULL)
1255 (void) __ns_ldap_freeParam((void ***)&enable_shadow);
1256 return (B_FALSE);
1257 }
1258
1259 /*
1260 * __ns_ldap_repAttr modifies ldap attributes of the 'dn' entry stored
1261 * on the LDAP server. 'service' indicates the type of database entries
1262 * to modify. When the Native LDAP client is configured with 'shadow update
1263 * enabled', Shadowshadow(4) entries can only be modified by privileged users.
1264 * Such users use the NS_LDAP_UPDATE_SHADOW flag to indicate the call is
1265 * for such a shadow(5) update, which would be forwarded to ldap_cachemgr
1266 * for performing the LDAP modify operation. ldap_cachemgr would call
1267 * this function again and use the special service NS_ADMIN_SHADOW_UPDATE
1268 * to identify itself, so that admin credential would be obtained and
1269 * the actual LDAP modify operation be done.
1270 */
1271 /*ARGSUSED*/
1272 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)1273 __ns_ldap_repAttr(
1274 const char *service,
1275 const char *dn,
1276 const ns_ldap_attr_t * const *attr,
1277 const ns_cred_t *cred,
1278 const int flags,
1279 ns_ldap_error_t ** errorp)
1280 {
1281 LDAPMod **mods;
1282 int rc = 0;
1283 boolean_t priv;
1284 boolean_t shadow_update_enabled = B_FALSE;
1285
1286 #ifdef DEBUG
1287 (void) fprintf(stderr, "__ns_ldap_repAttr START\n");
1288 #endif
1289 *errorp = NULL;
1290
1291 /* Sanity check */
1292 if (attr == NULL || *attr == NULL || dn == NULL)
1293 return (NS_LDAP_INVALID_PARAM);
1294
1295 /* Privileged shadow modify? */
1296 if ((flags & NS_LDAP_UPDATE_SHADOW) != 0 &&
1297 strcmp(service, "shadow") == 0) {
1298
1299 /* Shadow update enabled ? If not, error out */
1300 shadow_update_enabled = __ns_ldap_is_shadow_update_enabled();
1301 if (!shadow_update_enabled) {
1302 *errorp = __s_api_make_error(NS_CONFIG_NOTALLOW,
1303 gettext("Shadow Update is not enabled"));
1304 return (NS_LDAP_CONFIG);
1305 }
1306
1307 /* privileged shadow modify requires euid 0 or all zone privs */
1308 priv = (geteuid() == 0);
1309 if (!priv) {
1310 priv_set_t *ps = priv_allocset(); /* caller */
1311 priv_set_t *zs; /* zone */
1312
1313 (void) getppriv(PRIV_EFFECTIVE, ps);
1314 zs = priv_str_to_set("zone", ",", NULL);
1315 priv = priv_isequalset(ps, zs);
1316 priv_freeset(ps);
1317 priv_freeset(zs);
1318 }
1319 if (!priv)
1320 return (NS_LDAP_OP_FAILED);
1321
1322 rc = send_to_cachemgr(dn, (ns_ldap_attr_t **)attr, errorp);
1323 return (rc);
1324 }
1325
1326 if (cred == NULL)
1327 return (NS_LDAP_INVALID_PARAM);
1328
1329 /*
1330 * If service is NS_ADMIN_SHADOW_UPDATE, the caller should be
1331 * ldap_cachemgr. We need to get the admin cred to do work.
1332 * If the caller is not ldap_cachemgr, but use the service
1333 * NS_ADMIN_SHADOW_UPDATE, get_admin_passwd() will fail,
1334 * as the admin cred is not available to the caller.
1335 */
1336 if (strcmp(service, NS_ADMIN_SHADOW_UPDATE) == 0) {
1337 if ((rc = get_admin_passwd((ns_cred_t *)cred, errorp)) !=
1338 NS_LDAP_SUCCESS)
1339 return (rc);
1340 }
1341
1342 mods = __s_api_makeModList(service, attr, LDAP_MOD_REPLACE, flags);
1343 if (mods == NULL)
1344 return (NS_LDAP_MEMORY);
1345
1346 rc = write_state_machine(LDAP_REQ_MODIFY,
1347 (char *)dn, mods, cred, flags, errorp);
1348
1349 freeModList(mods);
1350 return (rc);
1351 }
1352
1353 /*ARGSUSED*/
1354 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)1355 __ns_ldap_addEntry(
1356 const char *service,
1357 const char *dn,
1358 const ns_ldap_entry_t *entry,
1359 const ns_cred_t *cred,
1360 const int flags,
1361 ns_ldap_error_t ** errorp)
1362 {
1363 char *new_dn = NULL;
1364 LDAPMod **mods = NULL;
1365 const ns_ldap_attr_t * const *attr;
1366 int nAttr = 0;
1367 int rc = 0;
1368
1369 #ifdef DEBUG
1370 (void) fprintf(stderr, "__ns_ldap_addEntry START\n");
1371 #endif
1372
1373 if ((entry == NULL) || (dn == NULL) || (cred == NULL))
1374 return (NS_LDAP_INVALID_PARAM);
1375 *errorp = NULL;
1376
1377 /* Construct array of LDAPMod representing attributes of new entry. */
1378
1379 nAttr = entry->attr_count;
1380 attr = (const ns_ldap_attr_t * const *)(entry->attr_pair);
1381 mods = __s_api_makeModListCount(service, attr, LDAP_MOD_ADD,
1382 nAttr, flags);
1383 if (mods == NULL) {
1384 return (NS_LDAP_MEMORY);
1385 }
1386
1387 rc = replace_mapped_attr_in_dn(service, dn, &new_dn);
1388 if (rc != NS_LDAP_SUCCESS) {
1389 freeModList(mods);
1390 return (rc);
1391 }
1392
1393 rc = write_state_machine(LDAP_REQ_ADD,
1394 new_dn ? new_dn : (char *)dn, mods, cred, flags, errorp);
1395
1396 if (new_dn)
1397 free(new_dn);
1398 freeModList(mods);
1399 return (rc);
1400 }
1401
1402
1403 /*ARGSUSED*/
1404 int
__ns_ldap_delEntry(const char * service,const char * dn,const ns_cred_t * cred,const int flags,ns_ldap_error_t ** errorp)1405 __ns_ldap_delEntry(
1406 const char *service,
1407 const char *dn,
1408 const ns_cred_t *cred,
1409 const int flags,
1410 ns_ldap_error_t ** errorp)
1411 {
1412 int rc;
1413
1414 #ifdef DEBUG
1415 (void) fprintf(stderr, "__ns_ldap_delEntry START\n");
1416 #endif
1417 if ((dn == NULL) || (cred == NULL))
1418 return (NS_LDAP_INVALID_PARAM);
1419
1420 *errorp = NULL;
1421
1422 rc = write_state_machine(LDAP_REQ_DELETE,
1423 (char *)dn, NULL, cred, flags, errorp);
1424
1425 return (rc);
1426 }
1427
1428 /*
1429 * Add Typed Entry Helper routines
1430 */
1431
1432 /*
1433 * Add Typed Entry Conversion routines
1434 */
1435
1436 static int
__s_add_attr(ns_ldap_entry_t * e,char * attrname,char * value)1437 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
1438 {
1439 ns_ldap_attr_t *a;
1440 char *v;
1441
1442 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1443 if (a == NULL)
1444 return (NS_LDAP_MEMORY);
1445 a->attrname = strdup(attrname);
1446 if (a->attrname == NULL)
1447 return (NS_LDAP_MEMORY);
1448 a->attrvalue = (char **)calloc(1, sizeof (char **));
1449 if (a->attrvalue == NULL)
1450 return (NS_LDAP_MEMORY);
1451 a->value_count = 1;
1452 a->attrvalue[0] = NULL;
1453 v = strdup(value);
1454 if (v == NULL)
1455 return (NS_LDAP_MEMORY);
1456 a->attrvalue[0] = v;
1457 e->attr_pair[e->attr_count] = a;
1458 e->attr_count++;
1459 return (NS_LDAP_SUCCESS);
1460 }
1461
1462 static int
__s_add_attrlist(ns_ldap_entry_t * e,char * attrname,char ** argv)1463 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
1464 {
1465 ns_ldap_attr_t *a;
1466 char *v;
1467 char **av;
1468 int i, j;
1469
1470 a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
1471 if (a == NULL)
1472 return (NS_LDAP_MEMORY);
1473 a->attrname = strdup(attrname);
1474 if (a->attrname == NULL)
1475 return (NS_LDAP_MEMORY);
1476
1477 for (i = 0, av = argv; *av != NULL; av++, i++)
1478 ;
1479
1480 a->attrvalue = (char **)calloc(i, sizeof (char *));
1481
1482 if (a->attrvalue == NULL)
1483 return (NS_LDAP_MEMORY);
1484
1485 a->value_count = i;
1486 for (j = 0; j < i; j++) {
1487 v = strdup(argv[j]);
1488 if (v == NULL)
1489 return (NS_LDAP_MEMORY);
1490 a->attrvalue[j] = v;
1491 }
1492 e->attr_pair[e->attr_count] = a;
1493 e->attr_count++;
1494 return (NS_LDAP_SUCCESS);
1495 }
1496
1497 static ns_ldap_entry_t *
__s_mk_entry(char ** objclass,int max_attr)1498 __s_mk_entry(char **objclass, int max_attr)
1499 {
1500 ns_ldap_entry_t *e;
1501 e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
1502 if (e == NULL)
1503 return (NULL);
1504 /* allocate attributes, +1 for objectclass, +1 for NULL terminator */
1505 e->attr_pair = (ns_ldap_attr_t **)
1506 calloc(max_attr + 2, sizeof (ns_ldap_attr_t *));
1507 if (e->attr_pair == NULL) {
1508 free(e);
1509 return (NULL);
1510 }
1511 e->attr_count = 0;
1512 if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
1513 free(e->attr_pair);
1514 free(e);
1515 return (NULL);
1516 }
1517 return (e);
1518 }
1519
1520
1521 /*
1522 * Conversion: passwd
1523 * Input format: struct passwd
1524 * Exported objectclass: posixAccount
1525 */
1526 static int
__s_cvt_passwd(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1527 __s_cvt_passwd(const void *data, char **rdn,
1528 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1529 {
1530 ns_ldap_entry_t *e;
1531 int rc;
1532 char trdn[RDNSIZE];
1533 /* routine specific */
1534 struct passwd *ptr;
1535 int max_attr = 9;
1536 char ibuf[10];
1537 static char *oclist[] = {
1538 "posixAccount",
1539 "shadowAccount",
1540 "account",
1541 "top",
1542 NULL
1543 };
1544
1545 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1546 return (NS_LDAP_OP_FAILED);
1547 *entry = e = __s_mk_entry(oclist, max_attr);
1548 if (e == NULL)
1549 return (NS_LDAP_MEMORY);
1550
1551 /* Convert the structure */
1552 ptr = (struct passwd *)data;
1553
1554 if (ptr->pw_name == NULL || ptr->pw_uid > MAXUID ||
1555 ptr->pw_gid > MAXUID || ptr->pw_dir == NULL) {
1556 __ns_ldap_freeEntry(e);
1557 *entry = NULL;
1558 return (NS_LDAP_INVALID_PARAM);
1559 }
1560
1561 /* Create an appropriate rdn */
1562 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->pw_name);
1563 *rdn = strdup(trdn);
1564 if (*rdn == NULL) {
1565 __ns_ldap_freeEntry(e);
1566 *entry = NULL;
1567 return (NS_LDAP_MEMORY);
1568 }
1569
1570 /* Error check the data and add the attributes */
1571 rc = __s_add_attr(e, "uid", ptr->pw_name);
1572 if (rc != NS_LDAP_SUCCESS) {
1573 __s_cvt_freeEntryRdn(entry, rdn);
1574 return (rc);
1575 }
1576 rc = __s_add_attr(e, "cn", ptr->pw_name);
1577 if (rc != NS_LDAP_SUCCESS) {
1578 __s_cvt_freeEntryRdn(entry, rdn);
1579 return (rc);
1580 }
1581
1582 if (ptr->pw_passwd != NULL &&
1583 ptr->pw_passwd[0] != '\0') {
1584 rc = __s_add_attr(e, "userPassword", ptr->pw_passwd);
1585 if (rc != NS_LDAP_SUCCESS) {
1586 __s_cvt_freeEntryRdn(entry, rdn);
1587 return (rc);
1588 }
1589 }
1590
1591 (void) sprintf(ibuf, "%u", ptr->pw_uid);
1592 rc = __s_add_attr(e, "uidNumber", ibuf);
1593 if (rc != NS_LDAP_SUCCESS) {
1594 __s_cvt_freeEntryRdn(entry, rdn);
1595 return (rc);
1596 }
1597
1598 (void) sprintf(ibuf, "%u", ptr->pw_gid);
1599 rc = __s_add_attr(e, "gidNumber", ibuf);
1600 if (rc != NS_LDAP_SUCCESS) {
1601 __s_cvt_freeEntryRdn(entry, rdn);
1602 return (rc);
1603 }
1604 if (ptr->pw_gecos != NULL &&
1605 ptr->pw_gecos[0] != '\0') {
1606 rc = __s_add_attr(e, "gecos", ptr->pw_gecos);
1607 if (rc != NS_LDAP_SUCCESS) {
1608 __s_cvt_freeEntryRdn(entry, rdn);
1609 return (rc);
1610 }
1611 }
1612
1613 rc = __s_add_attr(e, "homeDirectory", ptr->pw_dir);
1614 if (rc != NS_LDAP_SUCCESS) {
1615 __s_cvt_freeEntryRdn(entry, rdn);
1616 return (rc);
1617 }
1618 if (ptr->pw_shell != NULL &&
1619 ptr->pw_shell[0] != '\0') {
1620 rc = __s_add_attr(e, "loginShell", ptr->pw_shell);
1621 if (rc != NS_LDAP_SUCCESS) {
1622 __s_cvt_freeEntryRdn(entry, rdn);
1623 return (rc);
1624 }
1625 }
1626
1627 return (NS_LDAP_SUCCESS);
1628 }
1629
1630 /*
1631 * escape_str function escapes special characters in str and
1632 * copies to escstr string.
1633 *
1634 * return 0 for successful
1635 * 1 for fail
1636 */
escape_str(char * escstr,char * str)1637 static int escape_str(char *escstr, char *str)
1638 {
1639 int index = 0;
1640
1641 while ((*str != '\0') && (index < (RDNSIZE - 1))) {
1642 if (*str == '+' || *str == ';' || *str == '>' ||
1643 *str == '<' || *str == ',' || *str == '"' ||
1644 *str == '\\' || *str == '=' ||
1645 (*str == '#' && index == 0)) {
1646 *escstr++ = '\\';
1647 *escstr++ = *str++;
1648 index += 2;
1649 } else {
1650 *escstr++ = *str++;
1651 index++;
1652 }
1653 }
1654
1655 if (*str == '\0') {
1656 *escstr = '\0';
1657 return (0);
1658 } else {
1659 return (1);
1660 }
1661 }
1662
1663 /*
1664 * Conversion: project
1665 * Input format: struct project
1666 * Exported objectclass: SolarisProject
1667 */
1668 static int
__s_cvt_project(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1669 __s_cvt_project(const void *data, char **rdn,
1670 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1671 {
1672 ns_ldap_entry_t *e;
1673 int rc;
1674 char trdn[RDNSIZE];
1675
1676 /* routine specific */
1677 struct project *ptr;
1678 int max_attr = 9;
1679 char ibuf[11];
1680 static char *oclist[] = {
1681 "SolarisProject",
1682 "top",
1683 NULL
1684 };
1685
1686 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1687 return (NS_LDAP_OP_FAILED);
1688
1689 *entry = e = __s_mk_entry(oclist, max_attr);
1690 if (e == NULL)
1691 return (NS_LDAP_MEMORY);
1692
1693 /* Convert the structure */
1694 ptr = (struct project *)data;
1695
1696 if (ptr->pj_name == NULL || ptr->pj_projid > MAXUID) {
1697 __ns_ldap_freeEntry(e);
1698 *entry = NULL;
1699 return (NS_LDAP_INVALID_PARAM);
1700 }
1701
1702 /* Create an appropriate rdn */
1703 (void) snprintf(trdn, RDNSIZE, "SolarisProjectName=%s", ptr->pj_name);
1704 *rdn = strdup(trdn);
1705 if (*rdn == NULL) {
1706 __ns_ldap_freeEntry(e);
1707 *entry = NULL;
1708 return (NS_LDAP_MEMORY);
1709 }
1710
1711 /* Error check the data and add the attributes */
1712
1713 /* Project name */
1714 rc = __s_add_attr(e, "SolarisProjectName", ptr->pj_name);
1715 if (rc != NS_LDAP_SUCCESS) {
1716 __s_cvt_freeEntryRdn(entry, rdn);
1717 return (rc);
1718 }
1719
1720 /*
1721 * Project ID:
1722 * ibuf is 11 chars big, which should be enough for string
1723 * representation of 32bit number + nul-car
1724 */
1725 if (snprintf(ibuf, sizeof (ibuf), "%u", ptr->pj_projid) < 0) {
1726 __s_cvt_freeEntryRdn(entry, rdn);
1727 return (NS_LDAP_INVALID_PARAM);
1728 }
1729 rc = __s_add_attr(e, "SolarisProjectID", ibuf);
1730 if (rc != NS_LDAP_SUCCESS) {
1731 __s_cvt_freeEntryRdn(entry, rdn);
1732 return (rc);
1733 }
1734
1735 /* Comment/Description */
1736 if (ptr->pj_comment != NULL && ptr->pj_comment[0] != '\0') {
1737 rc = __s_add_attr(e, "description", ptr->pj_comment);
1738 if (rc != NS_LDAP_SUCCESS) {
1739 __s_cvt_freeEntryRdn(entry, rdn);
1740 return (rc);
1741 }
1742 }
1743
1744 /* Attributes */
1745 if (ptr->pj_attr != NULL && ptr->pj_attr[0] != '\0') {
1746 rc = __s_add_attr(e, "SolarisProjectAttr", ptr->pj_attr);
1747 if (rc != NS_LDAP_SUCCESS) {
1748 __s_cvt_freeEntryRdn(entry, rdn);
1749 return (rc);
1750 }
1751 }
1752
1753 /* Users */
1754 if (ptr->pj_users != NULL) {
1755 rc = __s_add_attrlist(e, "memberUid", ptr->pj_users);
1756 if (rc != NS_LDAP_SUCCESS) {
1757 __s_cvt_freeEntryRdn(entry, rdn);
1758 return (rc);
1759 }
1760 }
1761
1762 /* Groups */
1763 if (ptr->pj_groups != NULL) {
1764 rc = __s_add_attrlist(e, "memberGid", ptr->pj_groups);
1765 if (rc != NS_LDAP_SUCCESS) {
1766 __s_cvt_freeEntryRdn(entry, rdn);
1767 return (rc);
1768 }
1769 }
1770
1771
1772
1773 return (NS_LDAP_SUCCESS);
1774 }
1775 /*
1776 * Conversion: shadow
1777 * Input format: struct shadow
1778 * Exported objectclass: shadowAccount
1779 */
1780 static int
__s_cvt_shadow(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1781 __s_cvt_shadow(const void *data, char **rdn,
1782 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1783 {
1784 ns_ldap_entry_t *e;
1785 int rc;
1786 char trdn[RDNSIZE];
1787 /* routine specific */
1788 struct spwd *ptr;
1789 int max_attr = 10;
1790 char ibuf[10];
1791 static char *oclist[] = {
1792 "posixAccount",
1793 "shadowAccount",
1794 "account",
1795 "top",
1796 NULL
1797 };
1798
1799 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1800 return (NS_LDAP_OP_FAILED);
1801 *entry = e = __s_mk_entry(oclist, max_attr);
1802 if (e == NULL)
1803 return (NS_LDAP_MEMORY);
1804
1805 /* Convert the structure */
1806 ptr = (struct spwd *)data;
1807
1808 if (ptr->sp_namp == NULL) {
1809 __ns_ldap_freeEntry(e);
1810 *entry = NULL;
1811 return (NS_LDAP_INVALID_PARAM);
1812 }
1813
1814 /* Create an appropriate rdn */
1815 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->sp_namp);
1816 *rdn = strdup(trdn);
1817 if (*rdn == NULL) {
1818 __ns_ldap_freeEntry(e);
1819 *entry = NULL;
1820 return (NS_LDAP_MEMORY);
1821 }
1822
1823 /* Error check the data and add the attributes */
1824 rc = __s_add_attr(e, "uid", ptr->sp_namp);
1825 if (rc != NS_LDAP_SUCCESS) {
1826 __s_cvt_freeEntryRdn(entry, rdn);
1827 return (rc);
1828 }
1829
1830 if (ptr->sp_pwdp == NULL) {
1831 __s_cvt_freeEntryRdn(entry, rdn);
1832 return (NS_LDAP_INVALID_PARAM);
1833 } else {
1834 rc = __s_add_attr(e, "userPassword", ptr->sp_pwdp);
1835 if (rc != NS_LDAP_SUCCESS) {
1836 __s_cvt_freeEntryRdn(entry, rdn);
1837 return (rc);
1838 }
1839 }
1840 if (ptr->sp_lstchg >= 0) {
1841 (void) sprintf(ibuf, "%d", ptr->sp_lstchg);
1842 rc = __s_add_attr(e, "shadowLastChange", ibuf);
1843 if (rc != NS_LDAP_SUCCESS) {
1844 __s_cvt_freeEntryRdn(entry, rdn);
1845 return (rc);
1846 }
1847 }
1848 if (ptr->sp_min >= 0) {
1849 (void) sprintf(ibuf, "%d", ptr->sp_min);
1850 rc = __s_add_attr(e, "shadowMin", ibuf);
1851 if (rc != NS_LDAP_SUCCESS) {
1852 __s_cvt_freeEntryRdn(entry, rdn);
1853 return (rc);
1854 }
1855 }
1856 if (ptr->sp_max >= 0) {
1857 (void) sprintf(ibuf, "%d", ptr->sp_max);
1858 rc = __s_add_attr(e, "shadowMax", ibuf);
1859 if (rc != NS_LDAP_SUCCESS) {
1860 __s_cvt_freeEntryRdn(entry, rdn);
1861 return (rc);
1862 }
1863 }
1864 if (ptr->sp_warn >= 0) {
1865 (void) sprintf(ibuf, "%d", ptr->sp_warn);
1866 rc = __s_add_attr(e, "shadowWarning", ibuf);
1867 if (rc != NS_LDAP_SUCCESS) {
1868 __s_cvt_freeEntryRdn(entry, rdn);
1869 return (rc);
1870 }
1871 }
1872 if (ptr->sp_inact >= 0) {
1873 (void) sprintf(ibuf, "%d", ptr->sp_inact);
1874 rc = __s_add_attr(e, "shadowInactive", ibuf);
1875 if (rc != NS_LDAP_SUCCESS) {
1876 __s_cvt_freeEntryRdn(entry, rdn);
1877 return (rc);
1878 }
1879 }
1880 if (ptr->sp_expire >= 0) {
1881 (void) sprintf(ibuf, "%d", ptr->sp_expire);
1882 rc = __s_add_attr(e, "shadowExpire", ibuf);
1883 if (rc != NS_LDAP_SUCCESS) {
1884 __s_cvt_freeEntryRdn(entry, rdn);
1885 return (rc);
1886 }
1887 }
1888 (void) sprintf(ibuf, "%d", ptr->sp_flag);
1889 rc = __s_add_attr(e, "shadowFlag", ibuf);
1890 if (rc != NS_LDAP_SUCCESS) {
1891 __s_cvt_freeEntryRdn(entry, rdn);
1892 return (rc);
1893 }
1894
1895 return (NS_LDAP_SUCCESS);
1896 }
1897
1898
1899 /*
1900 * Conversion: group
1901 * Input format: struct group
1902 * Exported objectclass: posixGroup
1903 */
1904 static int
__s_cvt_group(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)1905 __s_cvt_group(const void *data, char **rdn,
1906 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
1907 {
1908 ns_ldap_entry_t *e;
1909 int rc;
1910 char trdn[RDNSIZE];
1911 /* routine specific */
1912 struct group *ptr;
1913 int i, j, k;
1914 char **nm, **lm;
1915 int max_attr = 4;
1916 char ibuf[10];
1917 static char *oclist[] = {
1918 "posixGroup",
1919 "top",
1920 NULL
1921 };
1922
1923 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
1924 return (NS_LDAP_OP_FAILED);
1925 *entry = e = __s_mk_entry(oclist, max_attr);
1926 if (e == NULL)
1927 return (NS_LDAP_MEMORY);
1928
1929 /* Convert the structure */
1930 ptr = (struct group *)data;
1931
1932 if (ptr->gr_name == NULL || ptr->gr_gid > MAXUID) {
1933 __ns_ldap_freeEntry(e);
1934 *entry = NULL;
1935 return (NS_LDAP_INVALID_PARAM);
1936 }
1937
1938 /* Create an appropriate rdn */
1939 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->gr_name);
1940 *rdn = strdup(trdn);
1941 if (*rdn == NULL) {
1942 __ns_ldap_freeEntry(e);
1943 *entry = NULL;
1944 return (NS_LDAP_MEMORY);
1945 }
1946
1947 /* Error check the data and add the attributes */
1948 rc = __s_add_attr(e, "cn", ptr->gr_name);
1949 if (rc != NS_LDAP_SUCCESS) {
1950 __s_cvt_freeEntryRdn(entry, rdn);
1951 return (rc);
1952 }
1953
1954 (void) sprintf(ibuf, "%u", ptr->gr_gid);
1955 rc = __s_add_attr(e, "gidNumber", ibuf);
1956 if (rc != NS_LDAP_SUCCESS) {
1957 __s_cvt_freeEntryRdn(entry, rdn);
1958 return (rc);
1959 }
1960 if (ptr->gr_passwd && ptr->gr_passwd[0] != '\0') {
1961 rc = __s_add_attr(e, "userPassword", ptr->gr_passwd);
1962 if (rc != NS_LDAP_SUCCESS) {
1963 __s_cvt_freeEntryRdn(entry, rdn);
1964 return (rc);
1965 }
1966 }
1967
1968 if (ptr->gr_mem && ptr->gr_mem[0]) {
1969 lm = ptr->gr_mem;
1970 for (i = 0; *lm; i++, lm++)
1971 ;
1972 lm = ptr->gr_mem;
1973 nm = (char **)calloc(i+2, sizeof (char *));
1974 if (nm == NULL) {
1975 __s_cvt_freeEntryRdn(entry, rdn);
1976 return (NS_LDAP_MEMORY);
1977 }
1978 for (j = 0; j < i; j++) {
1979 nm[j] = strdup(lm[j]);
1980 if (nm[j] == NULL) {
1981 for (k = 0; k < j; k++)
1982 free(nm[k]);
1983 free(nm);
1984 __s_cvt_freeEntryRdn(entry, rdn);
1985 return (NS_LDAP_MEMORY);
1986 }
1987 }
1988 rc = __s_add_attrlist(e, "memberUid", nm);
1989 for (j = 0; j < i; j++) {
1990 free(nm[j]);
1991 }
1992 free(nm);
1993 nm = NULL;
1994 if (rc != NS_LDAP_SUCCESS) {
1995 __s_cvt_freeEntryRdn(entry, rdn);
1996 return (rc);
1997 }
1998 }
1999
2000 return (NS_LDAP_SUCCESS);
2001 }
2002
2003 /*
2004 * Conversion: hosts
2005 * Input format: struct hostent
2006 * Exported objectclass: ipHost
2007 */
2008 static int
__s_cvt_hosts(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2009 __s_cvt_hosts(const void *data, char **rdn,
2010 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2011 {
2012 ns_ldap_entry_t *e;
2013 int rc;
2014 char trdn[RDNSIZE];
2015 /* routine specific */
2016 struct hostent *ptr;
2017 int max_attr = 6;
2018 int i, j, k;
2019 char **nm, **lm;
2020 static char *oclist[] = {
2021 "ipHost",
2022 "device",
2023 "top",
2024 NULL
2025 };
2026
2027 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2028 return (NS_LDAP_OP_FAILED);
2029 *entry = e = __s_mk_entry(oclist, max_attr);
2030 if (e == NULL)
2031 return (NS_LDAP_MEMORY);
2032
2033 /* Convert the structure */
2034 ptr = (struct hostent *)data;
2035
2036 if (ptr->h_name == NULL ||
2037 ptr->h_addr_list == NULL || ptr->h_addr_list[0] == NULL) {
2038 __ns_ldap_freeEntry(e);
2039 *entry = NULL;
2040 return (NS_LDAP_INVALID_PARAM);
2041 }
2042
2043 /* Create an appropriate rdn */
2044 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipHostNumber=%s",
2045 ptr->h_name, ptr->h_addr_list[0]);
2046 *rdn = strdup(trdn);
2047 if (*rdn == NULL) {
2048 __ns_ldap_freeEntry(e);
2049 *entry = NULL;
2050 return (NS_LDAP_MEMORY);
2051 }
2052
2053 /* Error check the data and add the attributes */
2054 if (ptr->h_aliases && ptr->h_aliases[0]) {
2055 lm = ptr->h_aliases;
2056 /*
2057 * If there is a description, 'i' will contain
2058 * the index of the description in the aliases list
2059 */
2060 for (i = 0; *lm && (*lm)[0] != '#'; i++, lm++)
2061 ;
2062 lm = ptr->h_aliases;
2063 nm = (char **)calloc(i+2, sizeof (char *));
2064 if (nm == NULL) {
2065 __s_cvt_freeEntryRdn(entry, rdn);
2066 return (NS_LDAP_MEMORY);
2067 }
2068 nm[0] = ptr->h_name;
2069 for (j = 0; j < i; j++)
2070 nm[j+1] = ptr->h_aliases[j];
2071
2072 rc = __s_add_attrlist(e, "cn", nm);
2073
2074 if (rc != NS_LDAP_SUCCESS) {
2075 __s_cvt_freeEntryRdn(entry, rdn);
2076 free(nm);
2077 return (rc);
2078 }
2079
2080 if (lm[i] && lm[i][0] == '#') {
2081 nm[0] = &(lm[i][1]);
2082 nm[1] = NULL;
2083 rc = __s_add_attrlist(e, "description", nm);
2084 }
2085 free(nm);
2086 nm = NULL;
2087 if (rc != NS_LDAP_SUCCESS) {
2088 __s_cvt_freeEntryRdn(entry, rdn);
2089 return (rc);
2090 }
2091 } else {
2092 rc = __s_add_attr(e, "cn", ptr->h_name);
2093 if (rc != NS_LDAP_SUCCESS) {
2094 __s_cvt_freeEntryRdn(entry, rdn);
2095 return (rc);
2096 }
2097 }
2098
2099 if (ptr->h_addr_list && ptr->h_addr_list[0]) {
2100 lm = ptr->h_addr_list;
2101 for (i = 0; *lm; i++, lm++)
2102 ;
2103 lm = ptr->h_addr_list;
2104 nm = (char **)calloc(i+2, sizeof (char *));
2105 if (nm == NULL) {
2106 __s_cvt_freeEntryRdn(entry, rdn);
2107 return (NS_LDAP_MEMORY);
2108 }
2109 for (j = 0; j < i; j++) {
2110 nm[j] = strdup(lm[j]);
2111 if (nm[j] == NULL) {
2112 for (k = 0; k < j; k++)
2113 free(nm[k]);
2114 free(nm);
2115 __s_cvt_freeEntryRdn(entry, rdn);
2116 return (NS_LDAP_MEMORY);
2117 }
2118 }
2119 rc = __s_add_attrlist(e, "ipHostNumber", nm);
2120 for (j = 0; j < i; j++) {
2121 free(nm[j]);
2122 }
2123 free(nm);
2124 nm = NULL;
2125 if (rc != NS_LDAP_SUCCESS) {
2126 __s_cvt_freeEntryRdn(entry, rdn);
2127 return (rc);
2128 }
2129 } else {
2130 __s_cvt_freeEntryRdn(entry, rdn);
2131 return (NS_LDAP_INVALID_PARAM);
2132 }
2133
2134 return (NS_LDAP_SUCCESS);
2135 }
2136
2137 /*
2138 * Conversion: rpc
2139 * Input format: struct rpcent
2140 * Exported objectclass: oncRpc
2141 */
2142 static int
__s_cvt_rpc(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2143 __s_cvt_rpc(const void *data, char **rdn,
2144 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2145 {
2146 ns_ldap_entry_t *e;
2147 int rc;
2148 char trdn[RDNSIZE];
2149 /* routine specific */
2150 struct rpcent *ptr;
2151 int max_attr = 3;
2152 int i, j;
2153 char **nm;
2154 char ibuf[10];
2155 static char *oclist[] = {
2156 "oncRpc",
2157 "top",
2158 NULL
2159 };
2160
2161 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2162 return (NS_LDAP_OP_FAILED);
2163 *entry = e = __s_mk_entry(oclist, max_attr);
2164 if (e == NULL)
2165 return (NS_LDAP_MEMORY);
2166
2167 /* Convert the structure */
2168 ptr = (struct rpcent *)data;
2169
2170 if (ptr->r_name == NULL || ptr->r_number < 0) {
2171 __ns_ldap_freeEntry(e);
2172 *entry = NULL;
2173 return (NS_LDAP_INVALID_PARAM);
2174 }
2175
2176 /* Create an appropriate rdn */
2177 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->r_name);
2178 *rdn = strdup(trdn);
2179 if (*rdn == NULL) {
2180 __ns_ldap_freeEntry(e);
2181 *entry = NULL;
2182 return (NS_LDAP_MEMORY);
2183 }
2184
2185 /* Error check the data and add the attributes */
2186 if (ptr->r_aliases && ptr->r_aliases[0]) {
2187 nm = ptr->r_aliases;
2188 for (i = 0; *nm; i++, nm++)
2189 ;
2190 nm = (char **)calloc(i+2, sizeof (char *));
2191 if (nm == NULL) {
2192 __s_cvt_freeEntryRdn(entry, rdn);
2193 return (NS_LDAP_MEMORY);
2194 }
2195 nm[0] = ptr->r_name;
2196 for (j = 0; j < i; j++)
2197 nm[j+1] = ptr->r_aliases[j];
2198
2199 rc = __s_add_attrlist(e, "cn", nm);
2200 free(nm);
2201 nm = NULL;
2202 if (rc != NS_LDAP_SUCCESS) {
2203 __s_cvt_freeEntryRdn(entry, rdn);
2204 return (rc);
2205 }
2206 } else {
2207 rc = __s_add_attr(e, "cn", ptr->r_name);
2208 if (rc != NS_LDAP_SUCCESS) {
2209 __s_cvt_freeEntryRdn(entry, rdn);
2210 return (rc);
2211 }
2212 }
2213
2214 if (ptr->r_number >= 0) {
2215 (void) sprintf(ibuf, "%d", ptr->r_number);
2216 rc = __s_add_attr(e, "oncRpcNumber", ibuf);
2217 if (rc != NS_LDAP_SUCCESS) {
2218 __s_cvt_freeEntryRdn(entry, rdn);
2219 return (rc);
2220 }
2221 }
2222
2223 return (NS_LDAP_SUCCESS);
2224
2225 }
2226
2227 /*
2228 * Conversion: protocols
2229 * Input format: struct protoent
2230 * Exported objectclass: ipProtocol
2231 */
2232 static int
__s_cvt_protocols(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2233 __s_cvt_protocols(const void *data, char **rdn,
2234 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2235 {
2236 ns_ldap_entry_t *e;
2237 int rc;
2238 char trdn[RDNSIZE];
2239 /* routine specific */
2240 struct protoent *ptr;
2241 int max_attr = 3;
2242 int i, j;
2243 char ibuf[10];
2244 char **nm;
2245 static char *oclist[] = {
2246 "ipProtocol",
2247 "top",
2248 NULL
2249 };
2250
2251 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2252 return (NS_LDAP_OP_FAILED);
2253 *entry = e = __s_mk_entry(oclist, max_attr);
2254 if (e == NULL)
2255 return (NS_LDAP_MEMORY);
2256
2257 /* Convert the structure */
2258 ptr = (struct protoent *)data;
2259
2260 if (ptr->p_name == NULL || ptr->p_proto < 0) {
2261 __ns_ldap_freeEntry(e);
2262 *entry = NULL;
2263 return (NS_LDAP_INVALID_PARAM);
2264 }
2265
2266 /* Create an appropriate rdn */
2267 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->p_name);
2268 *rdn = strdup(trdn);
2269 if (*rdn == NULL) {
2270 __ns_ldap_freeEntry(e);
2271 *entry = NULL;
2272 return (NS_LDAP_MEMORY);
2273 }
2274
2275 /* Error check the data and add the attributes */
2276 if (ptr->p_aliases && ptr->p_aliases[0]) {
2277 nm = ptr->p_aliases;
2278 for (i = 0; *nm; i++, nm++)
2279 ;
2280 nm = (char **)calloc(i+2, sizeof (char *));
2281 if (nm == NULL) {
2282 __s_cvt_freeEntryRdn(entry, rdn);
2283 return (NS_LDAP_MEMORY);
2284 }
2285 nm[0] = ptr->p_name;
2286 for (j = 0; j < i; j++)
2287 nm[j+1] = ptr->p_aliases[j];
2288
2289 rc = __s_add_attrlist(e, "cn", nm);
2290 free(nm);
2291 nm = NULL;
2292 if (rc != NS_LDAP_SUCCESS) {
2293 __s_cvt_freeEntryRdn(entry, rdn);
2294 return (rc);
2295 }
2296 } else {
2297 rc = __s_add_attr(e, "cn", ptr->p_name);
2298 if (rc != NS_LDAP_SUCCESS) {
2299 __s_cvt_freeEntryRdn(entry, rdn);
2300 return (rc);
2301 }
2302 }
2303
2304 (void) sprintf(ibuf, "%d", ptr->p_proto);
2305 rc = __s_add_attr(e, "ipProtocolNumber", ibuf);
2306 if (rc != NS_LDAP_SUCCESS) {
2307 __s_cvt_freeEntryRdn(entry, rdn);
2308 return (rc);
2309 }
2310
2311 return (NS_LDAP_SUCCESS);
2312
2313 }
2314
2315 /*
2316 * Conversion: services
2317 * Input format: struct servent
2318 * Exported objectclass: ipService
2319 */
2320 static int
__s_cvt_services(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2321 __s_cvt_services(const void *data, char **rdn,
2322 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2323 {
2324 ns_ldap_entry_t *e;
2325 int rc;
2326 char trdn[RDNSIZE];
2327 char esc_str[RDNSIZE];
2328 /* routine specific */
2329 struct servent *ptr;
2330 int max_attr = 4;
2331 int i, j;
2332 char ibuf[10];
2333 char **nm;
2334 static char *oclist[] = {
2335 "ipService",
2336 "top",
2337 NULL
2338 };
2339
2340 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2341 return (NS_LDAP_OP_FAILED);
2342 *entry = e = __s_mk_entry(oclist, max_attr);
2343 if (e == NULL)
2344 return (NS_LDAP_MEMORY);
2345
2346 /* Convert the structure */
2347 ptr = (struct servent *)data;
2348
2349 if (ptr->s_name == NULL || ptr->s_port < 0 || ptr->s_proto == NULL) {
2350 __ns_ldap_freeEntry(e);
2351 *entry = NULL;
2352 return (NS_LDAP_INVALID_PARAM);
2353 }
2354
2355 /*
2356 * Escape special characters in service name.
2357 */
2358 if (escape_str(esc_str, ptr->s_name) != 0) {
2359 __ns_ldap_freeEntry(e);
2360 *entry = NULL;
2361 return (NS_LDAP_INVALID_PARAM);
2362 }
2363
2364 /* Create an appropriate rdn */
2365 (void) snprintf(trdn, RDNSIZE, "cn=%s+ipServiceProtocol=%s",
2366 esc_str, ptr->s_proto);
2367
2368 *rdn = strdup(trdn);
2369 if (*rdn == NULL) {
2370 __ns_ldap_freeEntry(e);
2371 *entry = NULL;
2372 return (NS_LDAP_MEMORY);
2373 }
2374
2375 /* Error check the data and add the attributes */
2376 if (ptr->s_aliases && ptr->s_aliases[0]) {
2377 nm = ptr->s_aliases;
2378 for (i = 0; *nm; i++, nm++)
2379 ;
2380 nm = (char **)calloc(i+2, sizeof (char *));
2381 if (nm == NULL) {
2382 __s_cvt_freeEntryRdn(entry, rdn);
2383 return (NS_LDAP_MEMORY);
2384 }
2385 nm[0] = ptr->s_name;
2386 for (j = 0; j < i; j++)
2387 nm[j+1] = ptr->s_aliases[j];
2388
2389 rc = __s_add_attrlist(e, "cn", nm);
2390 free(nm);
2391 nm = NULL;
2392 if (rc != NS_LDAP_SUCCESS) {
2393 __s_cvt_freeEntryRdn(entry, rdn);
2394 return (rc);
2395 }
2396 } else {
2397 rc = __s_add_attr(e, "cn", ptr->s_name);
2398 if (rc != NS_LDAP_SUCCESS) {
2399 __s_cvt_freeEntryRdn(entry, rdn);
2400 return (rc);
2401 }
2402 }
2403
2404 (void) sprintf(ibuf, "%d", ptr->s_port);
2405 rc = __s_add_attr(e, "ipServicePort", ibuf);
2406 if (rc != NS_LDAP_SUCCESS) {
2407 __s_cvt_freeEntryRdn(entry, rdn);
2408 return (rc);
2409 }
2410 rc = __s_add_attr(e, "ipServiceProtocol", ptr->s_proto);
2411 if (rc != NS_LDAP_SUCCESS) {
2412 __s_cvt_freeEntryRdn(entry, rdn);
2413 return (rc);
2414 }
2415
2416 return (NS_LDAP_SUCCESS);
2417 }
2418
2419 /*
2420 * Conversion: networks
2421 * Input format: struct netent
2422 * Exported objectclass: ipNetwork
2423 */
2424 static int
__s_cvt_networks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2425 __s_cvt_networks(const void *data, char **rdn,
2426 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2427 {
2428 ns_ldap_entry_t *e;
2429 int rc;
2430 char trdn[RDNSIZE];
2431 /* routine specific */
2432 struct netent *ptr;
2433 int max_attr = 4;
2434 int i, j;
2435 char cp[64];
2436 char **nm;
2437 static char *oclist[] = {
2438 "ipNetwork",
2439 "top",
2440 NULL
2441 };
2442
2443 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2444 return (NS_LDAP_OP_FAILED);
2445 *entry = e = __s_mk_entry(oclist, max_attr);
2446 if (e == NULL)
2447 return (NS_LDAP_MEMORY);
2448
2449 /* Convert the structure */
2450 ptr = (struct netent *)data;
2451
2452 if (ptr->n_name == NULL || ptr->n_net == 0) {
2453 __ns_ldap_freeEntry(e);
2454 *entry = NULL;
2455 return (NS_LDAP_INVALID_PARAM);
2456 }
2457
2458 (void) snprintf(cp, sizeof (cp), "%d.%d.%d.%d",
2459 (ptr->n_net & 0xFF000000) >> 24,
2460 (ptr->n_net & 0x00FF0000) >> 16,
2461 (ptr->n_net & 0x0000FF00) >> 8,
2462 (ptr->n_net & 0x000000FF));
2463
2464 /* Create an appropriate rdn */
2465 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", cp);
2466 *rdn = strdup(trdn);
2467 if (*rdn == NULL) {
2468 __ns_ldap_freeEntry(e);
2469 *entry = NULL;
2470 return (NS_LDAP_MEMORY);
2471 }
2472
2473 /* Error check the data and add the attributes */
2474 if (ptr->n_aliases && ptr->n_aliases[0]) {
2475 nm = ptr->n_aliases;
2476 for (i = 0; *nm; i++, nm++)
2477 ;
2478 nm = (char **)calloc(i+2, sizeof (char *));
2479 if (nm == NULL) {
2480 __s_cvt_freeEntryRdn(entry, rdn);
2481 return (NS_LDAP_MEMORY);
2482 }
2483 nm[0] = ptr->n_name;
2484 for (j = 0; j < i; j++)
2485 nm[j+1] = ptr->n_aliases[j];
2486
2487 rc = __s_add_attrlist(e, "cn", nm);
2488 free(nm);
2489 nm = NULL;
2490 if (rc != NS_LDAP_SUCCESS) {
2491 __s_cvt_freeEntryRdn(entry, rdn);
2492 return (rc);
2493 }
2494 } else {
2495 rc = __s_add_attr(e, "cn", ptr->n_name);
2496 if (rc != NS_LDAP_SUCCESS) {
2497 __s_cvt_freeEntryRdn(entry, rdn);
2498 return (rc);
2499 }
2500 }
2501
2502 rc = __s_add_attr(e, "ipNetworkNumber", cp);
2503 if (rc != NS_LDAP_SUCCESS) {
2504 __s_cvt_freeEntryRdn(entry, rdn);
2505 return (rc);
2506 }
2507
2508 return (NS_LDAP_SUCCESS);
2509
2510 }
2511 /*
2512 * Conversion: netmasks
2513 * Input format: struct _ns_netmasks
2514 * Exported objectclass: ipNetwork
2515 */
2516 static int
__s_cvt_netmasks(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2517 __s_cvt_netmasks(const void *data, char **rdn,
2518 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2519 {
2520 ns_ldap_entry_t *e;
2521 int rc;
2522 char trdn[RDNSIZE];
2523 /* routine specific */
2524 struct _ns_netmasks *ptr;
2525 int max_attr = 4;
2526 static char *oclist[] = {
2527 "ipNetwork",
2528 "top",
2529 NULL
2530 };
2531
2532 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2533 return (NS_LDAP_OP_FAILED);
2534 *entry = e = __s_mk_entry(oclist, max_attr);
2535 if (e == NULL)
2536 return (NS_LDAP_MEMORY);
2537
2538 /* Convert the structure */
2539 ptr = (struct _ns_netmasks *)data;
2540
2541 if (ptr->netnumber == NULL) {
2542 __ns_ldap_freeEntry(e);
2543 *entry = NULL;
2544 return (NS_LDAP_INVALID_PARAM);
2545 }
2546
2547 /* Create an appropriate rdn */
2548 (void) snprintf(trdn, RDNSIZE, "ipNetworkNumber=%s", ptr->netnumber);
2549 *rdn = strdup(trdn);
2550 if (*rdn == NULL) {
2551 __ns_ldap_freeEntry(e);
2552 *entry = NULL;
2553 return (NS_LDAP_MEMORY);
2554 }
2555
2556 /* Error check the data and add the attributes */
2557 rc = __s_add_attr(e, "ipNetworkNumber", ptr->netnumber);
2558 if (rc != NS_LDAP_SUCCESS) {
2559 __s_cvt_freeEntryRdn(entry, rdn);
2560 return (rc);
2561 }
2562
2563 if (ptr->netmask != NULL) {
2564 rc = __s_add_attr(e, "ipNetmaskNumber", ptr->netmask);
2565 if (rc != NS_LDAP_SUCCESS) {
2566 __s_cvt_freeEntryRdn(entry, rdn);
2567 return (rc);
2568 }
2569 }
2570
2571 return (NS_LDAP_SUCCESS);
2572
2573 }
2574 /*
2575 * Conversion: netgroups
2576 * Input format: struct _ns_netgroups
2577 * Exported objectclass: nisNetgroup
2578 */
2579 static int
__s_cvt_netgroups(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2580 __s_cvt_netgroups(const void *data, char **rdn,
2581 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2582 {
2583 ns_ldap_entry_t *e;
2584 int rc;
2585 char trdn[RDNSIZE];
2586 /* routine specific */
2587 struct _ns_netgroups *ptr;
2588 int max_attr = 6;
2589 int i, j;
2590 char **nm;
2591 static char *oclist[] = {
2592 "nisNetgroup",
2593 "top",
2594 NULL
2595 };
2596
2597 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2598 return (NS_LDAP_OP_FAILED);
2599 *entry = e = __s_mk_entry(oclist, max_attr);
2600 if (e == NULL)
2601 return (NS_LDAP_MEMORY);
2602
2603 /* Convert the structure */
2604 ptr = (struct _ns_netgroups *)data;
2605
2606 if (ptr->name == NULL || *ptr->name == '\0') {
2607 __ns_ldap_freeEntry(e);
2608 *entry = NULL;
2609 return (NS_LDAP_INVALID_PARAM);
2610 }
2611
2612 /* Create an appropriate rdn */
2613 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2614 *rdn = strdup(trdn);
2615 if (*rdn == NULL) {
2616 __ns_ldap_freeEntry(e);
2617 *entry = NULL;
2618 return (NS_LDAP_MEMORY);
2619 }
2620
2621 rc = __s_add_attr(e, "cn", ptr->name);
2622 if (rc != NS_LDAP_SUCCESS) {
2623 __s_cvt_freeEntryRdn(entry, rdn);
2624 return (rc);
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 || *ptr->name == '\0') {
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 rc = __s_add_attr(e, "cn", ptr->name);
2719 if (rc != NS_LDAP_SUCCESS) {
2720 __s_cvt_freeEntryRdn(entry, rdn);
2721 return (rc);
2722 }
2723
2724 /* Error check the data and add the attributes */
2725 if (ptr->param && ptr->param[0]) {
2726 nm = ptr->param;
2727 for (i = 0; *nm; i++, nm++)
2728 ;
2729 nm = (char **)calloc(i+2, sizeof (char *));
2730 if (nm == NULL) {
2731 __s_cvt_freeEntryRdn(entry, rdn);
2732 return (NS_LDAP_MEMORY);
2733 }
2734 for (j = 0; j < i; j++)
2735 nm[j] = ptr->param[j];
2736
2737 rc = __s_add_attrlist(e, "bootParameter", nm);
2738 free(nm);
2739 nm = NULL;
2740 if (rc != NS_LDAP_SUCCESS) {
2741 __s_cvt_freeEntryRdn(entry, rdn);
2742 return (rc);
2743 }
2744 }
2745
2746 return (NS_LDAP_SUCCESS);
2747
2748 }
2749 /*
2750 * Conversion: ethers
2751 * Input format: struct _ns_ethers
2752 * Exported objectclass: ieee802Device, device
2753 */
2754 static int
__s_cvt_ethers(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2755 __s_cvt_ethers(const void *data, char **rdn,
2756 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2757 {
2758 ns_ldap_entry_t *e;
2759 int rc;
2760 char trdn[RDNSIZE];
2761 /* routine specific */
2762 struct _ns_ethers *ptr;
2763 int max_attr = 4;
2764 static char *oclist[] = {
2765 "ieee802Device",
2766 "device",
2767 "top",
2768 NULL
2769 };
2770
2771 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2772 return (NS_LDAP_OP_FAILED);
2773 *entry = e = __s_mk_entry(oclist, max_attr);
2774 if (e == NULL)
2775 return (NS_LDAP_MEMORY);
2776
2777 /* Convert the structure */
2778 ptr = (struct _ns_ethers *)data;
2779
2780 if (ptr->name == NULL || *ptr->name == '\0' || ptr->ether == NULL) {
2781 __ns_ldap_freeEntry(e);
2782 *entry = NULL;
2783 return (NS_LDAP_INVALID_PARAM);
2784 }
2785
2786 /* Create an appropriate rdn */
2787 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2788 *rdn = strdup(trdn);
2789 if (*rdn == NULL) {
2790 __ns_ldap_freeEntry(e);
2791 *entry = NULL;
2792 return (NS_LDAP_MEMORY);
2793 }
2794
2795 /* Error check the data and add the attributes */
2796 rc = __s_add_attr(e, "cn", ptr->name);
2797 if (rc != NS_LDAP_SUCCESS) {
2798 __s_cvt_freeEntryRdn(entry, rdn);
2799 return (rc);
2800 }
2801
2802 rc = __s_add_attr(e, "macAddress", ptr->ether);
2803 if (rc != NS_LDAP_SUCCESS) {
2804 __s_cvt_freeEntryRdn(entry, rdn);
2805 return (rc);
2806 }
2807
2808 return (NS_LDAP_SUCCESS);
2809 }
2810 /*
2811 * This function is used when processing an ethers (objectclass: ieee802Device)
2812 * or a bootparams (objectclass: bootableDevice) entry, and the entry is
2813 * already found in LDAP. Since both ethers and bootparams share the same
2814 * LDAP container, we want to check that the entry found in LDAP is:
2815 * - either the same entry (same cn, same objectclass): we don't do anything
2816 * in this case
2817 * - or an entry which does not have the objectclass we are interesting in:
2818 * in this case, we modify the existing entry by adding the relevant
2819 * objectclass (ieee802Device or bootableDevice) and the relevant attribute(s)
2820 * from the attribute list previously computing by the relevant conversion
2821 * function.
2822 * Note: from conversion functions __s_cvt_ethers() and __s_cvt_bootparams()
2823 * we know that there is only 1 more attribute today to add (macAddress
2824 * or bootParameter)
2825 */
2826 #define _MAX_ATTR_ETHBOOTP 2
2827 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)2828 modify_ethers_bootp(
2829 const char *service,
2830 const char *rdn,
2831 const char *fulldn,
2832 const ns_ldap_attr_t * const *attrlist,
2833 const ns_cred_t *cred,
2834 const int flags,
2835 ns_ldap_error_t **errorp)
2836 {
2837 char filter[BUFSIZ];
2838 ns_ldap_result_t *resultp;
2839 int rc = 0;
2840 int i;
2841 ns_ldap_attr_t *new_attrlist[_MAX_ATTR_ETHBOOTP+1];
2842 ns_ldap_attr_t new_attrlist0;
2843 char *new_attrvalue0[1];
2844 const ns_ldap_attr_t * const *aptr = attrlist;
2845 ns_ldap_attr_t *aptr2;
2846 ns_ldap_error_t *new_errorp = NULL;
2847
2848 if (rdn == NULL || fulldn == NULL || attrlist == NULL ||
2849 errorp == NULL || service == NULL)
2850 return (NS_LDAP_OP_FAILED);
2851
2852 bzero(&new_attrlist, sizeof (new_attrlist));
2853 bzero(&new_attrlist0, sizeof (new_attrlist0));
2854 new_attrlist[0] = &new_attrlist0;
2855 new_attrlist[0]->attrvalue = new_attrvalue0;
2856
2857 new_attrlist[0]->attrname = "objectclass";
2858 new_attrlist[0]->value_count = 1;
2859 if (strcasecmp(service, "ethers") == 0) {
2860 (void) snprintf(&filter[0], sizeof (filter),
2861 "(&(objectClass=ieee802Device)(%s))", rdn);
2862 new_attrlist[0]->attrvalue[0] = "ieee802Device";
2863 } else {
2864 (void) snprintf(&filter[0], sizeof (filter),
2865 "(&(objectClass=bootableDevice)(%s))", rdn);
2866 new_attrlist[0]->attrvalue[0] = "bootableDevice";
2867 }
2868
2869 rc = __ns_ldap_list(service, filter, NULL, (const char **)NULL,
2870 NULL, NS_LDAP_SCOPE_SUBTREE, &resultp, &new_errorp,
2871 NULL, NULL);
2872
2873 switch (rc) {
2874 case NS_LDAP_SUCCESS:
2875 /*
2876 * entry already exists for this service
2877 * return NS_LDAP_INTERNAL and do not modify the incoming errorp
2878 */
2879 rc = NS_LDAP_INTERNAL;
2880 break;
2881 case NS_LDAP_NOTFOUND:
2882 /*
2883 * entry not found with the given objectclasss but entry exists
2884 * hence add the relevant attribute (macAddress or bootparams).
2885 */
2886 i = 1;
2887 while (*aptr && (i < _MAX_ATTR_ETHBOOTP)) {
2888 /* aptr2 needed here to avoid lint warning */
2889 aptr2 = (ns_ldap_attr_t *)*aptr++;
2890 if ((strcasecmp(aptr2->attrname, "cn") != 0) &&
2891 (strcasecmp(aptr2->attrname,
2892 "objectclass") != 0)) {
2893 new_attrlist[i++] = (ns_ldap_attr_t *)aptr2;
2894 }
2895 }
2896
2897 if (i != _MAX_ATTR_ETHBOOTP) {
2898 /* we haven't found all expected attributes */
2899 rc = NS_LDAP_OP_FAILED;
2900 break;
2901 }
2902
2903 aptr = (const ns_ldap_attr_t * const *) new_attrlist;
2904 /* clean errorp first */
2905 (void) __ns_ldap_freeError(errorp);
2906 rc = __ns_ldap_addAttr(service, fulldn, aptr, cred, flags,
2907 errorp);
2908 break;
2909 default:
2910 /*
2911 * unexpected error happenned
2912 * returning relevant error
2913 */
2914 (void) __ns_ldap_freeError(errorp);
2915 *errorp = new_errorp;
2916 break;
2917 }
2918
2919 return (rc);
2920 }
2921
2922 /*
2923 * Conversion: publickey
2924 * Input format: struct _ns_pubkey
2925 * Exported objectclass: NisKeyObject
2926 */
2927 static int
__s_cvt_publickey(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2928 __s_cvt_publickey(const void *data, char **rdn,
2929 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2930 {
2931 ns_ldap_entry_t *e;
2932 int rc;
2933 char trdn[RDNSIZE];
2934 /* routine specific */
2935 struct _ns_pubkey *ptr;
2936 int max_attr = 3;
2937 static char *oclist[] = {
2938 "NisKeyObject",
2939 NULL
2940 };
2941
2942 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
2943 return (NS_LDAP_OP_FAILED);
2944 *entry = e = __s_mk_entry(oclist, max_attr);
2945 if (e == NULL)
2946 return (NS_LDAP_MEMORY);
2947
2948 /* Convert the structure */
2949 ptr = (struct _ns_pubkey *)data;
2950
2951 if (ptr->name == NULL || *ptr->name == '\0' || ptr->pubkey == NULL ||
2952 ptr->privkey == NULL) {
2953 __ns_ldap_freeEntry(e);
2954 *entry = NULL;
2955 return (NS_LDAP_INVALID_PARAM);
2956 }
2957
2958 /* Create an appropriate rdn */
2959 if (ptr->hostcred == NS_HOSTCRED_FALSE)
2960 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
2961 else
2962 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
2963 *rdn = strdup(trdn);
2964 if (*rdn == NULL) {
2965 __ns_ldap_freeEntry(e);
2966 *entry = NULL;
2967 return (NS_LDAP_MEMORY);
2968 }
2969
2970 /* Error check the data and add the attributes */
2971
2972 rc = __s_add_attr(e, "nisPublickey", ptr->pubkey);
2973 if (rc != NS_LDAP_SUCCESS) {
2974 __s_cvt_freeEntryRdn(entry, rdn);
2975 return (rc);
2976 }
2977
2978 rc = __s_add_attr(e, "nisSecretkey", ptr->privkey);
2979 if (rc != NS_LDAP_SUCCESS) {
2980 __s_cvt_freeEntryRdn(entry, rdn);
2981 return (rc);
2982 }
2983
2984 return (NS_LDAP_SUCCESS);
2985 }
2986 /*
2987 * Conversion: aliases
2988 * Input format: struct _ns_alias
2989 * Exported objectclass: mailGroup
2990 */
2991 static int
__s_cvt_aliases(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)2992 __s_cvt_aliases(const void *data, char **rdn,
2993 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
2994 {
2995 ns_ldap_entry_t *e;
2996 int rc;
2997 char trdn[RDNSIZE];
2998 /* routine specific */
2999 struct _ns_alias *ptr;
3000 int max_attr = 4;
3001 int i, j;
3002 char **nm;
3003 static char *oclist[] = {
3004 "mailGroup",
3005 "top",
3006 NULL
3007 };
3008
3009 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3010 return (NS_LDAP_OP_FAILED);
3011 *entry = e = __s_mk_entry(oclist, max_attr);
3012 if (e == NULL)
3013 return (NS_LDAP_MEMORY);
3014
3015 /* Convert the structure */
3016 ptr = (struct _ns_alias *)data;
3017
3018 if (ptr->alias == NULL || *ptr->alias == '\0') {
3019 __ns_ldap_freeEntry(e);
3020 *entry = NULL;
3021 return (NS_LDAP_INVALID_PARAM);
3022 }
3023
3024 /* Create an appropriate rdn */
3025 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->alias);
3026 *rdn = strdup(trdn);
3027 if (*rdn == NULL) {
3028 __ns_ldap_freeEntry(e);
3029 *entry = NULL;
3030 return (NS_LDAP_MEMORY);
3031 }
3032
3033 rc = __s_add_attr(e, "mail", (char *)ptr->alias);
3034 if (rc != NS_LDAP_SUCCESS) {
3035 __s_cvt_freeEntryRdn(entry, rdn);
3036 return (rc);
3037 }
3038
3039 /* Error check the data and add the attributes */
3040 if (ptr->member && ptr->member[0]) {
3041 nm = ptr->member;
3042 for (i = 0; *nm; i++, nm++)
3043 ;
3044 nm = (char **)calloc(i+2, sizeof (char *));
3045 if (nm == NULL) {
3046 __s_cvt_freeEntryRdn(entry, rdn);
3047 return (NS_LDAP_MEMORY);
3048 }
3049 for (j = 0; j < i; j++)
3050 nm[j] = ptr->member[j];
3051
3052 rc = __s_add_attrlist(e, "mgrpRFC822MailMember", nm);
3053 free(nm);
3054 nm = NULL;
3055 if (rc != NS_LDAP_SUCCESS) {
3056 __s_cvt_freeEntryRdn(entry, rdn);
3057 return (rc);
3058 }
3059 }
3060
3061 return (NS_LDAP_SUCCESS);
3062
3063 }
3064 /*
3065 * Conversion: automount
3066 * Input format: struct _ns_automount
3067 * Exported objectclass: automount
3068 */
3069 static int
__s_cvt_auto_mount(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3070 __s_cvt_auto_mount(const void *data, char **rdn,
3071 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3072 {
3073 ns_ldap_entry_t *e;
3074 int rc;
3075 char trdn[RDNSIZE];
3076 /* routine specific */
3077 struct _ns_automount *ptr;
3078 int max_attr = 6;
3079 void **paramVal = NULL;
3080 char **mappedschema = NULL;
3081 int version1 = 0;
3082 static char *oclist[] = {
3083 NULL,
3084 "top",
3085 NULL
3086 };
3087
3088 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3089 return (NS_LDAP_OP_FAILED);
3090
3091 /* determine profile version number */
3092 rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, ¶mVal, errorp);
3093 if (paramVal && *paramVal &&
3094 strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
3095 version1 = 1;
3096 if (paramVal)
3097 (void) __ns_ldap_freeParam(¶mVal);
3098 if (rc && errorp)
3099 (void) __ns_ldap_freeError(errorp);
3100
3101 /* use old schema for version 1 profiles */
3102 if (version1)
3103 oclist[0] = "nisObject";
3104 else
3105 oclist[0] = "automount";
3106
3107 *entry = e = __s_mk_entry(oclist, max_attr);
3108 if (e == NULL)
3109 return (NS_LDAP_MEMORY);
3110
3111 /* Convert the structure */
3112 ptr = (struct _ns_automount *)data;
3113
3114 if (ptr->key == NULL || *ptr->key == '\0' || ptr->value == NULL ||
3115 ptr->mapname == NULL) {
3116 __ns_ldap_freeEntry(e);
3117 *entry = NULL;
3118 return (NS_LDAP_INVALID_PARAM);
3119 }
3120
3121 /* Create an appropriate rdn */
3122 (void) snprintf(trdn, RDNSIZE, version1 ? "cn=%s" : "automountKey=%s",
3123 ptr->key);
3124 *rdn = strdup(trdn);
3125 if (*rdn == NULL) {
3126 __ns_ldap_freeEntry(e);
3127 *entry = NULL;
3128 return (NS_LDAP_MEMORY);
3129 }
3130
3131 rc = __s_add_attr(e, version1 ? "cn" : "automountKey",
3132 (char *)ptr->key);
3133 if (rc != NS_LDAP_SUCCESS) {
3134 __s_cvt_freeEntryRdn(entry, rdn);
3135 return (rc);
3136 }
3137
3138 rc = __s_add_attr(e, version1 ? "nisMapEntry" : "automountInformation",
3139 (char *)ptr->value);
3140 if (rc != NS_LDAP_SUCCESS) {
3141 __s_cvt_freeEntryRdn(entry, rdn);
3142 return (rc);
3143 }
3144
3145 /*
3146 * even for version 2, if automount is mapped to nisObject we
3147 * still need 'nisMapName' attribute
3148 */
3149 mappedschema = __ns_ldap_getMappedObjectClass("automount", "automount");
3150 if (mappedschema && mappedschema[0] &&
3151 strcasecmp(mappedschema[0], "nisObject") == 0)
3152 version1 = 1;
3153 if (mappedschema)
3154 __s_api_free2dArray(mappedschema);
3155
3156 if (version1) {
3157 rc = __s_add_attr(e, "nisMapName", (char *)ptr->mapname);
3158 if (rc != NS_LDAP_SUCCESS) {
3159 __s_cvt_freeEntryRdn(entry, rdn);
3160 return (rc);
3161 }
3162 }
3163
3164 return (NS_LDAP_SUCCESS);
3165 }
3166 /*
3167 * Conversion: auth_attr
3168 * Input format: authstr_t
3169 * Exported objectclass: SolarisAuthAttr
3170 */
3171 static int
__s_cvt_authattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3172 __s_cvt_authattr(const void *data, char **rdn,
3173 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3174 {
3175 ns_ldap_entry_t *e;
3176 int rc;
3177 char trdn[RDNSIZE];
3178 /* routine specific */
3179 authstr_t *ptr;
3180 int max_attr = 6;
3181 static char *oclist[] = {
3182 "SolarisAuthAttr",
3183 "top",
3184 NULL
3185 };
3186
3187 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3188 return (NS_LDAP_OP_FAILED);
3189
3190 *entry = e = __s_mk_entry(oclist, max_attr);
3191 if (e == NULL)
3192 return (NS_LDAP_MEMORY);
3193
3194 /* Convert the structure */
3195 ptr = (authstr_t *)data;
3196
3197 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3198 __ns_ldap_freeEntry(e);
3199 *entry = NULL;
3200 return (NS_LDAP_INVALID_PARAM);
3201 }
3202
3203 /* Create an appropriate rdn */
3204 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3205 *rdn = strdup(trdn);
3206 if (*rdn == NULL) {
3207 __ns_ldap_freeEntry(e);
3208 *entry = NULL;
3209 return (NS_LDAP_MEMORY);
3210 }
3211
3212 rc = __s_add_attr(e, "cn", ptr->name);
3213 if (rc != NS_LDAP_SUCCESS) {
3214 __s_cvt_freeEntryRdn(entry, rdn);
3215 return (rc);
3216 }
3217
3218 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3219 if (rc != NS_LDAP_SUCCESS) {
3220 __s_cvt_freeEntryRdn(entry, rdn);
3221 return (rc);
3222 }
3223
3224 if (ptr->res1 != NULL) {
3225 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3226 if (rc != NS_LDAP_SUCCESS) {
3227 __s_cvt_freeEntryRdn(entry, rdn);
3228 return (rc);
3229 }
3230 }
3231
3232 if (ptr->res2 != NULL) {
3233 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3234 if (rc != NS_LDAP_SUCCESS) {
3235 __s_cvt_freeEntryRdn(entry, rdn);
3236 return (rc);
3237 }
3238 }
3239
3240 if (ptr->short_desc != NULL) {
3241 rc = __s_add_attr(e, "SolarisAttrShortDesc", ptr->short_desc);
3242 if (rc != NS_LDAP_SUCCESS) {
3243 __s_cvt_freeEntryRdn(entry, rdn);
3244 return (rc);
3245 }
3246 }
3247
3248 if (ptr->long_desc != NULL) {
3249 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->long_desc);
3250 if (rc != NS_LDAP_SUCCESS) {
3251 __s_cvt_freeEntryRdn(entry, rdn);
3252 return (rc);
3253 }
3254 }
3255
3256 return (NS_LDAP_SUCCESS);
3257 }
3258 /*
3259 * Conversion: exec_attr
3260 * Input format: execstr_t
3261 * Exported objectclass: SolarisExecAttr
3262 */
3263 static int
__s_cvt_execattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3264 __s_cvt_execattr(const void *data, char **rdn,
3265 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3266 {
3267 ns_ldap_entry_t *e;
3268 int rc;
3269 char trdn[RDNSIZE];
3270 char esc_str[RDNSIZE];
3271 /* routine specific */
3272 execstr_t *ptr;
3273 int max_attr = 7;
3274 static char *oclist[] = {
3275 "SolarisExecAttr",
3276 "SolarisProfAttr",
3277 "top",
3278 NULL
3279 };
3280
3281 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3282 return (NS_LDAP_OP_FAILED);
3283
3284 *entry = e = __s_mk_entry(oclist, max_attr);
3285 if (e == NULL)
3286 return (NS_LDAP_MEMORY);
3287
3288 /* Convert the structure */
3289 ptr = (execstr_t *)data;
3290
3291 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3292 ptr->policy == NULL || ptr->policy[0] == '\0' ||
3293 ptr->type == NULL || ptr->type[0] == '\0' ||
3294 ptr->id == NULL || ptr->id[0] == '\0') {
3295 __ns_ldap_freeEntry(e);
3296 *entry = NULL;
3297 return (NS_LDAP_INVALID_PARAM);
3298 }
3299
3300 /*
3301 * Escape special characters in ProfileID.
3302 */
3303 if (escape_str(esc_str, ptr->id) != 0) {
3304 __ns_ldap_freeEntry(e);
3305 *entry = NULL;
3306 return (NS_LDAP_INVALID_PARAM);
3307 }
3308
3309 /* Create an appropriate rdn */
3310 (void) snprintf(trdn, RDNSIZE, "cn=%s+SolarisKernelSecurityPolicy=%s"
3311 "+SolarisProfileType=%s+SolarisProfileId=%s",
3312 ptr->name, ptr->policy, ptr->type, esc_str);
3313
3314 *rdn = strdup(trdn);
3315 if (*rdn == NULL) {
3316 __ns_ldap_freeEntry(e);
3317 *entry = NULL;
3318 return (NS_LDAP_MEMORY);
3319 }
3320
3321 rc = __s_add_attr(e, "cn", ptr->name);
3322 if (rc != NS_LDAP_SUCCESS) {
3323 __s_cvt_freeEntryRdn(entry, rdn);
3324 return (rc);
3325 }
3326
3327 rc = __s_add_attr(e, "SolarisKernelSecurityPolicy", ptr->policy);
3328 if (rc != NS_LDAP_SUCCESS) {
3329 __s_cvt_freeEntryRdn(entry, rdn);
3330 return (rc);
3331 }
3332
3333 rc = __s_add_attr(e, "SolarisProfileType", ptr->type);
3334 if (rc != NS_LDAP_SUCCESS) {
3335 __s_cvt_freeEntryRdn(entry, rdn);
3336 return (rc);
3337 }
3338
3339 rc = __s_add_attr(e, "SolarisProfileId", ptr->id);
3340 if (rc != NS_LDAP_SUCCESS) {
3341 __s_cvt_freeEntryRdn(entry, rdn);
3342 return (rc);
3343 }
3344
3345 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3346 if (rc != NS_LDAP_SUCCESS) {
3347 __s_cvt_freeEntryRdn(entry, rdn);
3348 return (rc);
3349 }
3350
3351 if (ptr->res1 != NULL) {
3352 rc = __s_add_attr(e, "SolarisAttrRes1", ptr->res1);
3353 if (rc != NS_LDAP_SUCCESS) {
3354 __s_cvt_freeEntryRdn(entry, rdn);
3355 return (rc);
3356 }
3357 }
3358
3359 if (ptr->res2 != NULL) {
3360 rc = __s_add_attr(e, "SolarisAttrRes2", ptr->res2);
3361 if (rc != NS_LDAP_SUCCESS) {
3362 __s_cvt_freeEntryRdn(entry, rdn);
3363 return (rc);
3364 }
3365 }
3366
3367 return (NS_LDAP_SUCCESS);
3368 }
3369 /*
3370 * Conversion: prof_attr
3371 * Input format: profstr_t
3372 * Exported objectclass: SolarisProfAttr
3373 */
3374 static int
__s_cvt_profattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3375 __s_cvt_profattr(const void *data, char **rdn,
3376 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3377 {
3378 ns_ldap_entry_t *e;
3379 int rc;
3380 char trdn[RDNSIZE];
3381 /* routine specific */
3382 profstr_t *ptr;
3383 int max_attr = 5;
3384 static char *oclist[] = {
3385 "SolarisProfAttr",
3386 "top",
3387 NULL
3388 };
3389
3390 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3391 return (NS_LDAP_OP_FAILED);
3392
3393 *entry = e = __s_mk_entry(oclist, max_attr);
3394 if (e == NULL)
3395 return (NS_LDAP_MEMORY);
3396
3397 /* Convert the structure */
3398 ptr = (profstr_t *)data;
3399
3400 if (ptr->name == NULL || ptr->name[0] == '\0' || ptr->attr == NULL) {
3401 __ns_ldap_freeEntry(e);
3402 *entry = NULL;
3403 return (NS_LDAP_INVALID_PARAM);
3404 }
3405
3406 /* Create an appropriate rdn */
3407 (void) snprintf(trdn, RDNSIZE, "cn=%s", ptr->name);
3408 *rdn = strdup(trdn);
3409 if (*rdn == NULL) {
3410 __ns_ldap_freeEntry(e);
3411 *entry = NULL;
3412 return (NS_LDAP_MEMORY);
3413 }
3414
3415 rc = __s_add_attr(e, "cn", ptr->name);
3416 if (rc != NS_LDAP_SUCCESS) {
3417 __s_cvt_freeEntryRdn(entry, rdn);
3418 return (rc);
3419 }
3420
3421 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3422 if (rc != NS_LDAP_SUCCESS) {
3423 __s_cvt_freeEntryRdn(entry, rdn);
3424 return (rc);
3425 }
3426
3427 if (ptr->res1 != NULL) {
3428 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3429 if (rc != NS_LDAP_SUCCESS) {
3430 __s_cvt_freeEntryRdn(entry, rdn);
3431 return (rc);
3432 }
3433 }
3434
3435 if (ptr->res2 != NULL) {
3436 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3437 if (rc != NS_LDAP_SUCCESS) {
3438 __s_cvt_freeEntryRdn(entry, rdn);
3439 return (rc);
3440 }
3441 }
3442
3443 if (ptr->desc != NULL) {
3444 rc = __s_add_attr(e, "SolarisAttrLongDesc", ptr->desc);
3445 if (rc != NS_LDAP_SUCCESS) {
3446 __s_cvt_freeEntryRdn(entry, rdn);
3447 return (rc);
3448 }
3449 }
3450
3451 return (NS_LDAP_SUCCESS);
3452 }
3453 /*
3454 * Conversion: user_attr
3455 * Input format: userstr_t
3456 * Exported objectclass: SolarisUserAttr
3457 */
3458 static int
__s_cvt_userattr(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3459 __s_cvt_userattr(const void *data, char **rdn,
3460 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3461 {
3462 ns_ldap_entry_t *e;
3463 int rc;
3464 char trdn[RDNSIZE];
3465 /* routine specific */
3466 userstr_t *ptr;
3467 int max_attr = 5;
3468 static char *oclist[] = {
3469 "SolarisUserAttr",
3470 NULL
3471 };
3472
3473 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3474 return (NS_LDAP_OP_FAILED);
3475
3476 *entry = e = __s_mk_entry(oclist, max_attr);
3477 if (e == NULL)
3478 return (NS_LDAP_MEMORY);
3479
3480 /* Convert the structure */
3481 ptr = (userstr_t *)data;
3482
3483 if (ptr->name == NULL || ptr->name[0] == '\0' ||
3484 ptr->attr == NULL) {
3485 __ns_ldap_freeEntry(e);
3486 *entry = NULL;
3487 return (NS_LDAP_INVALID_PARAM);
3488 }
3489
3490 /* Create an appropriate rdn */
3491 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->name);
3492 *rdn = strdup(trdn);
3493 if (*rdn == NULL) {
3494 __ns_ldap_freeEntry(e);
3495 *entry = NULL;
3496 return (NS_LDAP_MEMORY);
3497 }
3498
3499 /*
3500 * SolarisUserAttr has no uid attribute
3501 */
3502
3503 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attr);
3504 if (rc != NS_LDAP_SUCCESS) {
3505 __s_cvt_freeEntryRdn(entry, rdn);
3506 return (rc);
3507 }
3508
3509 if (ptr->qualifier != NULL) {
3510 rc = __s_add_attr(e, "SolarisUserQualifier", ptr->qualifier);
3511 if (rc != NS_LDAP_SUCCESS) {
3512 __s_cvt_freeEntryRdn(entry, rdn);
3513 return (rc);
3514 }
3515 }
3516
3517 if (ptr->res1 != NULL) {
3518 rc = __s_add_attr(e, "SolarisAttrReserved1", ptr->res1);
3519 if (rc != NS_LDAP_SUCCESS) {
3520 __s_cvt_freeEntryRdn(entry, rdn);
3521 return (rc);
3522 }
3523 }
3524
3525 if (ptr->res2 != NULL) {
3526 rc = __s_add_attr(e, "SolarisAttrReserved2", ptr->res2);
3527 if (rc != NS_LDAP_SUCCESS) {
3528 __s_cvt_freeEntryRdn(entry, rdn);
3529 return (rc);
3530 }
3531 }
3532
3533 return (NS_LDAP_SUCCESS);
3534 }
3535 /*
3536 * Conversion: audit_user
3537 * Input format: au_user_str_t
3538 * Exported objectclass: SolarisAuditUser
3539 */
3540 static int
__s_cvt_audituser(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3541 __s_cvt_audituser(const void *data, char **rdn,
3542 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3543 {
3544 ns_ldap_entry_t *e;
3545 int rc;
3546 char trdn[RDNSIZE];
3547 /* routine specific */
3548 au_user_str_t *ptr;
3549 int max_attr = 3;
3550 static char *oclist[] = {
3551 "SolarisAuditUser",
3552 NULL
3553 };
3554
3555 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3556 return (NS_LDAP_OP_FAILED);
3557
3558 *entry = e = __s_mk_entry(oclist, max_attr);
3559 if (e == NULL)
3560 return (NS_LDAP_MEMORY);
3561
3562 /* Convert the structure */
3563 ptr = (au_user_str_t *)data;
3564
3565 if (ptr->au_name == NULL || ptr->au_name[0] == '\0') {
3566 __ns_ldap_freeEntry(e);
3567 *entry = NULL;
3568 return (NS_LDAP_INVALID_PARAM);
3569 }
3570
3571 /* Create an appropriate rdn */
3572 (void) snprintf(trdn, RDNSIZE, "uid=%s", ptr->au_name);
3573 *rdn = strdup(trdn);
3574 if (*rdn == NULL) {
3575 __ns_ldap_freeEntry(e);
3576 *entry = NULL;
3577 return (NS_LDAP_MEMORY);
3578 }
3579
3580 /*
3581 * Solaris AuditUser has no uid attribute
3582 */
3583
3584 if (ptr->au_always != NULL) {
3585 rc = __s_add_attr(e, "SolarisAuditAlways", ptr->au_always);
3586 if (rc != NS_LDAP_SUCCESS) {
3587 __s_cvt_freeEntryRdn(entry, rdn);
3588 return (rc);
3589 }
3590 }
3591
3592 if (ptr->au_never != NULL) {
3593 rc = __s_add_attr(e, "SolarisAuditNever", ptr->au_never);
3594 if (rc != NS_LDAP_SUCCESS) {
3595 __s_cvt_freeEntryRdn(entry, rdn);
3596 return (rc);
3597 }
3598 }
3599
3600 return (NS_LDAP_SUCCESS);
3601 }
3602 /*
3603 * Conversion: tnrhtp
3604 * Input format: tsol_tpstr_t
3605 * Exported objectclass: ipTnetTemplate
3606 */
3607 static int
__s_cvt_tnrhtp(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3608 __s_cvt_tnrhtp(const void *data, char **rdn,
3609 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3610 {
3611 ns_ldap_entry_t *e;
3612 int rc;
3613 char trdn[RDNSIZE];
3614 char esc_str[RDNSIZE];
3615 /* routine specific */
3616 int max_attr = 2;
3617 tsol_tpstr_t *ptr;
3618 static char *oclist[] = {
3619 "ipTnetTemplate",
3620 "top",
3621 NULL
3622 };
3623
3624 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3625 return (NS_LDAP_OP_FAILED);
3626
3627 *entry = e = __s_mk_entry(oclist, max_attr);
3628 if (e == NULL)
3629 return (NS_LDAP_MEMORY);
3630
3631 /* Convert the structure */
3632 ptr = (tsol_tpstr_t *)data;
3633
3634 if (ptr->template == NULL || *ptr->template == '\0') {
3635 __ns_ldap_freeEntry(e);
3636 *entry = NULL;
3637 return (NS_LDAP_INVALID_PARAM);
3638 }
3639
3640 /*
3641 * Escape special characters in Template name.
3642 */
3643 if (escape_str(esc_str, ptr->template) != 0) {
3644 __ns_ldap_freeEntry(e);
3645 *entry = NULL;
3646 return (NS_LDAP_INVALID_PARAM);
3647 }
3648
3649 /* Create an appropriate rdn */
3650 (void) snprintf(trdn, RDNSIZE, "ipTnetTemplateName=%s", esc_str);
3651 *rdn = strdup(trdn);
3652 if (*rdn == NULL) {
3653 __ns_ldap_freeEntry(e);
3654 *entry = NULL;
3655 return (NS_LDAP_MEMORY);
3656 }
3657
3658 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3659 if (rc != NS_LDAP_SUCCESS) {
3660 __s_cvt_freeEntryRdn(entry, rdn);
3661 return (rc);
3662 }
3663
3664 rc = __s_add_attr(e, "SolarisAttrKeyValue", ptr->attrs);
3665 if (rc != NS_LDAP_SUCCESS) {
3666 __s_cvt_freeEntryRdn(entry, rdn);
3667 return (rc);
3668 }
3669
3670 return (NS_LDAP_SUCCESS);
3671 }
3672 /*
3673 * Conversion: tnrhdb
3674 * Input format: tsol_rhstr_t
3675 * Exported objectclass: ipTnetHost
3676 */
3677 static int
__s_cvt_tnrhdb(const void * data,char ** rdn,ns_ldap_entry_t ** entry,ns_ldap_error_t ** errorp)3678 __s_cvt_tnrhdb(const void *data, char **rdn,
3679 ns_ldap_entry_t **entry, ns_ldap_error_t **errorp)
3680 {
3681 ns_ldap_entry_t *e;
3682 int rc;
3683 char trdn[RDNSIZE];
3684 /* routine specific */
3685 tsol_rhstr_t *ptr;
3686 int max_attr = 2;
3687 static char *oclist[] = {
3688 "ipTnetHost",
3689 "ipTnetTemplate",
3690 "top",
3691 NULL
3692 };
3693
3694 if (data == NULL || rdn == NULL || entry == NULL || errorp == NULL)
3695 return (NS_LDAP_OP_FAILED);
3696
3697 *entry = e = __s_mk_entry(oclist, max_attr);
3698 if (e == NULL)
3699 return (NS_LDAP_MEMORY);
3700
3701 /* Convert the structure */
3702 ptr = (tsol_rhstr_t *)data;
3703
3704 if (ptr->address == NULL || *ptr->address == '\0' ||
3705 ptr->template == NULL || *ptr->template == '\0') {
3706 __ns_ldap_freeEntry(e);
3707 *entry = NULL;
3708 return (NS_LDAP_INVALID_PARAM);
3709 }
3710
3711 /* Create an appropriate rdn */
3712 (void) snprintf(trdn, RDNSIZE, "ipTnetNumber=%s", ptr->address);
3713 *rdn = strdup(trdn);
3714 if (*rdn == NULL) {
3715 __ns_ldap_freeEntry(e);
3716 *entry = NULL;
3717 return (NS_LDAP_MEMORY);
3718 }
3719
3720 rc = __s_add_attr(e, "ipTnetNumber", ptr->address);
3721 if (rc != NS_LDAP_SUCCESS) {
3722 __s_cvt_freeEntryRdn(entry, rdn);
3723 return (rc);
3724 }
3725
3726 rc = __s_add_attr(e, "ipTnetTemplateName", ptr->template);
3727 if (rc != NS_LDAP_SUCCESS) {
3728 __s_cvt_freeEntryRdn(entry, rdn);
3729 return (rc);
3730 }
3731
3732 return (NS_LDAP_SUCCESS);
3733 }
3734 /*
3735 * Add Typed Entry Conversion data structures
3736 */
3737
3738 typedef struct __ns_cvt_type {
3739 const char *service;
3740 int flags;
3741 #define AE 1 /* alway add entries */
3742 int (*cvt_rtn)(const void *data,
3743 char **rdn,
3744 ns_ldap_entry_t **entry,
3745 ns_ldap_error_t **errorp);
3746 } __ns_cvt_type_t;
3747
3748 static __ns_cvt_type_t __s_cvtlist[] = {
3749 { NS_LDAP_TYPE_PASSWD, 0, __s_cvt_passwd },
3750 { NS_LDAP_TYPE_GROUP, 0, __s_cvt_group },
3751 { NS_LDAP_TYPE_HOSTS, 0, __s_cvt_hosts },
3752 { NS_LDAP_TYPE_IPNODES, 0, __s_cvt_hosts },
3753 { NS_LDAP_TYPE_RPC, 0, __s_cvt_rpc },
3754 { NS_LDAP_TYPE_PROTOCOLS, 0, __s_cvt_protocols },
3755 { NS_LDAP_TYPE_NETWORKS, 0, __s_cvt_networks },
3756 { NS_LDAP_TYPE_NETGROUP, 0, __s_cvt_netgroups },
3757 { NS_LDAP_TYPE_ALIASES, 0, __s_cvt_aliases },
3758 { NS_LDAP_TYPE_SERVICES, 0, __s_cvt_services },
3759 { NS_LDAP_TYPE_ETHERS, 0, __s_cvt_ethers },
3760 { NS_LDAP_TYPE_SHADOW, 0, __s_cvt_shadow },
3761 { NS_LDAP_TYPE_NETMASKS, 0, __s_cvt_netmasks },
3762 { NS_LDAP_TYPE_BOOTPARAMS, 0, __s_cvt_bootparams },
3763 { NS_LDAP_TYPE_AUTHATTR, 0, __s_cvt_authattr },
3764 { NS_LDAP_TYPE_EXECATTR, 0, __s_cvt_execattr },
3765 { NS_LDAP_TYPE_PROFILE, 0, __s_cvt_profattr },
3766 { NS_LDAP_TYPE_USERATTR, AE, __s_cvt_userattr },
3767 { NS_LDAP_TYPE_AUTOMOUNT, 0, __s_cvt_auto_mount },
3768 { NS_LDAP_TYPE_PUBLICKEY, AE, __s_cvt_publickey },
3769 { NS_LDAP_TYPE_AUUSER, AE, __s_cvt_audituser },
3770 { NS_LDAP_TYPE_TNRHTP, 0, __s_cvt_tnrhtp },
3771 { NS_LDAP_TYPE_TNRHDB, 0, __s_cvt_tnrhdb },
3772 { NS_LDAP_TYPE_PROJECT, 0, __s_cvt_project },
3773 { NULL, 0, NULL },
3774 };
3775
3776 /*
3777 * Add Typed Entry Routine
3778 */
3779
3780 /*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)3781 int __ns_ldap_addTypedEntry(
3782 const char *servicetype,
3783 const char *basedn,
3784 const void *data,
3785 const int create,
3786 const ns_cred_t *cred,
3787 const int flags,
3788 ns_ldap_error_t **errorp)
3789 {
3790 char *rdn = NULL, *fulldn = NULL;
3791 void **paramVal = NULL;
3792 ns_ldap_entry_t *entry = NULL;
3793 const ns_ldap_attr_t *const *modattrlist;
3794 ns_ldap_search_desc_t **sdlist;
3795 char **dns = NULL;
3796 char trdn[RDNSIZE];
3797 char service[BUFSIZE];
3798 int rc = 0;
3799 int automount = 0;
3800 int i, s;
3801
3802 rc = NS_LDAP_OP_FAILED;
3803 for (s = 0; __s_cvtlist[s].service != NULL; s++) {
3804 if (__s_cvtlist[s].cvt_rtn == NULL)
3805 continue;
3806 if (strcasecmp(__s_cvtlist[s].service, servicetype) == 0)
3807 break;
3808 /* Or, check if the servicetype is auto_ */
3809 if (strcmp(__s_cvtlist[s].service,
3810 NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
3811 strncasecmp(servicetype, NS_LDAP_TYPE_AUTOMOUNT,
3812 sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0) {
3813 automount++;
3814 break;
3815 }
3816 }
3817 if (__s_cvtlist[s].service == NULL)
3818 return (rc);
3819
3820 /* Convert the data */
3821 rc = (*__s_cvtlist[s].cvt_rtn)(data, &rdn, &entry, errorp);
3822 if (rc != NS_LDAP_SUCCESS) {
3823 __s_cvt_freeEntryRdn(&entry, &rdn);
3824 return (rc);
3825 }
3826 if (rdn == NULL) {
3827 __ns_ldap_freeEntry(entry);
3828 return (NS_LDAP_OP_FAILED);
3829 }
3830
3831 if (strcmp(servicetype, "publickey") == 0) {
3832 struct _ns_pubkey *ptr;
3833 ptr = (struct _ns_pubkey *)data;
3834 if (ptr->hostcred == NS_HOSTCRED_TRUE)
3835 (void) strcpy(service, "hosts");
3836 else
3837 (void) strcpy(service, "passwd");
3838 } else
3839 (void) strcpy(service, servicetype);
3840
3841 /* Create the Full DN */
3842 if (basedn == NULL) {
3843 rc = __s_api_get_SSD_from_SSDtoUse_service(service,
3844 &sdlist, errorp);
3845 if (rc != NS_LDAP_SUCCESS) {
3846 __s_cvt_freeEntryRdn(&entry, &rdn);
3847 return (rc);
3848 }
3849
3850 if (sdlist == NULL) {
3851 rc = __s_api_getDNs(&dns, service, errorp);
3852 if (rc != NS_LDAP_SUCCESS) {
3853 if (dns) {
3854 __s_api_free2dArray(dns);
3855 dns = NULL;
3856 }
3857 __s_cvt_freeEntryRdn(&entry, &rdn);
3858 return (rc);
3859 }
3860 (void) snprintf(trdn, RDNSIZE, "%s,%s", rdn, dns[0]);
3861 __s_api_free2dArray(dns);
3862 } else {
3863 if (sdlist[0]->basedn) {
3864 (void) snprintf(trdn, RDNSIZE, "%s,%s",
3865 rdn, sdlist[0]->basedn);
3866 } else {
3867 __s_cvt_freeEntryRdn(&entry, &rdn);
3868 return (NS_LDAP_OP_FAILED);
3869 }
3870 }
3871 i = strlen(trdn) - 1;
3872 if (trdn[i] == COMMATOK) {
3873 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3874 ¶mVal, errorp);
3875 if (rc != NS_LDAP_SUCCESS) {
3876 __s_cvt_freeEntryRdn(&entry, &rdn);
3877 return (rc);
3878 }
3879 i = strlen(trdn) + strlen((char *)(paramVal[0])) + 1;
3880 fulldn = (char *)calloc(i, 1);
3881 if (fulldn == NULL) {
3882 (void) __ns_ldap_freeParam(¶mVal);
3883 __s_cvt_freeEntryRdn(&entry, &rdn);
3884 return (NS_LDAP_MEMORY);
3885 }
3886 (void) snprintf(fulldn, i, "%s%s", trdn,
3887 (char *)(paramVal[0]));
3888 (void) __ns_ldap_freeParam(¶mVal);
3889 } else {
3890 fulldn = strdup(trdn);
3891 if (fulldn == NULL) {
3892 __s_cvt_freeEntryRdn(&entry, &rdn);
3893 return (NS_LDAP_MEMORY);
3894 }
3895 }
3896 } else {
3897 i = strlen(rdn) + strlen(basedn) + 2;
3898 fulldn = (char *)calloc(i, 1);
3899 if (fulldn == NULL) {
3900 __s_cvt_freeEntryRdn(&entry, &rdn);
3901 return (NS_LDAP_MEMORY);
3902 }
3903 (void) snprintf(fulldn, i, "%s,%s", rdn, basedn);
3904 }
3905
3906 modattrlist = (const ns_ldap_attr_t * const *)entry->attr_pair;
3907 /* Check to see if the entry exists already */
3908 /* May need to delete or update first */
3909
3910 if (create != 1) {
3911 /* Modify the entry */
3912 /*
3913 * To add a shadow-like entry, the addTypedEntry function
3914 * would call __ns_ldap_repAttr first, and if server says
3915 * LDAP_NO_SUCH_OBJECT, then it tries __ns_ldap_addEntry.
3916 * This is to allow a netmask entry to be added even if the
3917 * base network entry is not in the directory. It would work
3918 * because the difference between the schema for the network
3919 * and netmask data contains only MAY attributes.
3920 *
3921 * But for shadow data, the attributes do not have MUST
3922 * attributes the base entry needs, so if the __ns_ldap_addEntry
3923 * is executed, it would fail. The real reason, however, is that
3924 * the base entry did not exist. So returning
3925 * LDAP_OBJECT_CLASS_VIOLATION would just confused.
3926 */
3927 if ((__s_cvtlist[s].flags & AE) != 0)
3928 rc = __ns_ldap_addAttr(service, fulldn, modattrlist,
3929 cred, flags, errorp);
3930 else {
3931 rc = __ns_ldap_repAttr(service, fulldn, modattrlist,
3932 cred, flags, errorp);
3933 if (rc == NS_LDAP_INTERNAL && *errorp &&
3934 (*errorp)->status == LDAP_NO_SUCH_OBJECT) {
3935 (void) __ns_ldap_freeError(errorp);
3936 rc = __ns_ldap_addEntry(service, fulldn,
3937 entry, cred, flags, errorp);
3938 if (rc == NS_LDAP_INTERNAL && *errorp &&
3939 (*errorp)->status ==
3940 LDAP_OBJECT_CLASS_VIOLATION)
3941 (*errorp)->status = LDAP_NO_SUCH_OBJECT;
3942 }
3943 }
3944 } else {
3945 /* Add the entry */
3946 rc = __ns_ldap_addEntry(service, fulldn, entry,
3947 cred, flags, errorp);
3948 if (rc == NS_LDAP_INTERNAL && *errorp &&
3949 (*errorp)->status == LDAP_ALREADY_EXISTS &&
3950 ((strcmp(service, "ethers") == 0) ||
3951 (strcmp(service, "bootparams") == 0))) {
3952 rc = modify_ethers_bootp(service, rdn, fulldn,
3953 modattrlist, cred, flags, errorp);
3954 }
3955 }
3956
3957 /* Free up entry created by conversion routine */
3958 if (fulldn != NULL)
3959 free(fulldn);
3960 __s_cvt_freeEntryRdn(&entry, &rdn);
3961 return (rc);
3962 }
3963
3964
3965 /*
3966 * Append the default base dn to the dn
3967 * when it ends with ','.
3968 * e.g.
3969 * SSD = service:ou=foo,
3970 */
3971 int
__s_api_append_default_basedn(const char * dn,char ** new_dn,int * allocated,ns_ldap_error_t ** errp)3972 __s_api_append_default_basedn(const char *dn, char **new_dn, int *allocated,
3973 ns_ldap_error_t **errp)
3974 {
3975
3976 int rc = NS_LDAP_SUCCESS, len = 0;
3977 void **param = NULL;
3978 char *str = NULL;
3979
3980 *allocated = FALSE;
3981 *new_dn = NULL;
3982
3983 if (dn == NULL)
3984 return (NS_LDAP_INVALID_PARAM);
3985
3986 rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
3987 (void ***)¶m, errp);
3988
3989 if (rc != NS_LDAP_SUCCESS) {
3990 if (param)
3991 (void) __ns_ldap_freeParam(¶m);
3992 return (rc);
3993 }
3994
3995 len = strlen(dn);
3996 str = ((char **)param)[0];
3997 len = len + strlen(str) +1;
3998 *new_dn = (char *)malloc(len);
3999 if (*new_dn == NULL) {
4000 (void) __ns_ldap_freeParam(¶m);
4001 return (NS_LDAP_MEMORY);
4002 }
4003 *allocated = TRUE;
4004
4005 (void) strcpy(*new_dn, dn);
4006 (void) strcat(*new_dn, str);
4007
4008 (void) __ns_ldap_freeParam(¶m);
4009 return (NS_LDAP_SUCCESS);
4010 }
4011
4012 /*
4013 * Flatten the input ns_ldap_attr_t list, 'attr', and convert it into an
4014 * ldap_strlist_t structure in buffer 'buf', to be used by ldap_cachemgr.
4015 * The output contains a count, a list of offsets, which show where the
4016 * corresponding copied attribute type and attribute value are located.
4017 * For example, for dn=aaaa, userpassword=bbbb, shadowlastchange=cccc,
4018 * the output is the ldap_strlist_t structure with: ldap_count = 6,
4019 * (buf + ldap_offsets[0]) -> "dn"
4020 * (buf + ldap_offsets[1]) -> "aaaa"
4021 * (buf + ldap_offsets[2]) -> "userPassword"
4022 * (buf + ldap_offsets[3]) -> "bbbb"
4023 * (buf + ldap_offsets[4]) -> "shadowlastchange"
4024 * (buf + ldap_offsets[5]) -> "cccc"
4025 * and all the string data shown above copied into the buffer after
4026 * the offset array. The total length of the data will be the return
4027 * value, or -1 if error.
4028 */
4029 static int
attr2list(const char * dn,ns_ldap_attr_t ** attr,char * buf,int bufsize)4030 attr2list(const char *dn, ns_ldap_attr_t **attr,
4031 char *buf, int bufsize)
4032 {
4033 int c = 0;
4034 char *ap;
4035 int ao;
4036 ldap_strlist_t *al = (ldap_strlist_t *)buf;
4037 ns_ldap_attr_t *a = (ns_ldap_attr_t *)*attr;
4038 ns_ldap_attr_t **aptr = (ns_ldap_attr_t **)attr;
4039
4040 /* bufsize > strlen(dn) + strlen("dn") + 1 ('\0') */
4041 if ((strlen(dn) + 2 + 1) >= bufsize)
4042 return (-1);
4043
4044 /* count number of attributes */
4045 while (*aptr++)
4046 c++;
4047 al->ldap_count = 2 + c * 2;
4048 ao = sizeof (al->ldap_count) + sizeof (al->ldap_offsets[0]) *
4049 al->ldap_count;
4050 if (ao > bufsize)
4051 return (-1);
4052 al->ldap_offsets[0] = ao;
4053 ap = buf + ao;
4054 ao += 3;
4055
4056 /* copy entry DN */
4057 if (ao > bufsize)
4058 return (-1);
4059 (void) strlcpy(ap, "dn", bufsize);
4060 ap += 3;
4061
4062 al->ldap_offsets[1] = ao;
4063 ao += strlen(dn) + 1;
4064 if (ao > bufsize)
4065 return (-1);
4066 (void) strlcpy(ap, dn, bufsize);
4067 ap = buf + ao;
4068
4069 aptr = attr;
4070 for (c = 2; c < al->ldap_count; c++, aptr++) {
4071 a = *aptr;
4072 if (a->attrname == NULL || a->attrvalue == NULL ||
4073 a->value_count != 1 || a->attrvalue[0] == NULL)
4074 return (-1);
4075 al->ldap_offsets[c] = ao;
4076 ao += strlen(a->attrname) + 1;
4077 if (ao > bufsize)
4078 return (-1);
4079 (void) strlcpy(ap, a->attrname, bufsize);
4080 ap = buf + ao;
4081
4082 c++;
4083 al->ldap_offsets[c] = ao;
4084 ao += strlen(a->attrvalue[0]) + 1;
4085 (void) strlcpy(ap, a->attrvalue[0], bufsize);
4086 ap = buf + ao;
4087 };
4088
4089 return (ao);
4090 }
4091
4092 /*
4093 * Send a modify request to the ldap_cachemgr daemon
4094 * which will use the admin credential to perform the
4095 * operation.
4096 */
4097
4098 static int
send_to_cachemgr(const char * dn,ns_ldap_attr_t ** attr,ns_ldap_error_t ** errorp)4099 send_to_cachemgr(
4100 const char *dn,
4101 ns_ldap_attr_t **attr,
4102 ns_ldap_error_t **errorp)
4103 {
4104 union {
4105 ldap_data_t s_d;
4106 char s_b[DOORBUFFERSIZE];
4107 } space;
4108
4109 ldap_data_t *sptr;
4110 int ndata;
4111 int adata;
4112 int len;
4113 int rc;
4114 char errstr[MAXERROR];
4115 ldap_admin_mod_result_t *admin_result;
4116
4117 *errorp = NULL;
4118 (void) memset(space.s_b, 0, DOORBUFFERSIZE);
4119 len = attr2list(dn, attr, (char *)&space.s_d.ldap_call.ldap_u.strlist,
4120 sizeof (space) - offsetof(ldap_return_t, ldap_u));
4121 if (len <= 0)
4122 return (NS_LDAP_INVALID_PARAM);
4123
4124 adata = sizeof (ldap_call_t) + len;
4125 ndata = sizeof (space);
4126 space.s_d.ldap_call.ldap_callnumber = ADMINMODIFY;
4127 sptr = &space.s_d;
4128
4129 switch (__ns_ldap_trydoorcall(&sptr, &ndata, &adata)) {
4130 case NS_CACHE_SUCCESS:
4131 break;
4132 case NS_CACHE_NOTFOUND:
4133 (void) snprintf(errstr, sizeof (errstr),
4134 gettext("Door call ADMINMODIFY to "
4135 "ldap_cachemgr failed - error: %d"),
4136 space.s_d.ldap_ret.ldap_errno);
4137 MKERROR(LOG_WARNING, *errorp, NS_CONFIG_CACHEMGR,
4138 strdup(errstr), NS_LDAP_MEMORY);
4139 return (NS_LDAP_OP_FAILED);
4140 default:
4141 return (NS_LDAP_OP_FAILED);
4142 }
4143
4144 admin_result = &sptr->ldap_ret.ldap_u.admin_result;
4145 if (admin_result->ns_err == NS_LDAP_SUCCESS)
4146 rc = NS_LDAP_SUCCESS;
4147 else {
4148 rc = admin_result->ns_err;
4149 if (admin_result->msg_size == 0)
4150 *errorp = __s_api_make_error(admin_result->status,
4151 NULL);
4152 else
4153 *errorp = __s_api_make_error(admin_result->status,
4154 admin_result->msg);
4155 }
4156
4157 /* clean up the door call */
4158 if (sptr != &space.s_d) {
4159 (void) munmap((char *)sptr, ndata);
4160 }
4161
4162 return (rc);
4163 }
4164