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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* libsldap - cachemgr side configuration components */
27
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <stdlib.h>
31 #include <libintl.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <syslog.h>
39 #include <locale.h>
40 #include <errno.h>
41 #include <sys/time.h>
42
43 #include "ns_sldap.h"
44 #include "ns_internal.h"
45 #include "ns_cache_door.h"
46
47 #define ALWAYS 1
48
49
50 /*
51 * **************************************************************
52 * Configuration File Routines
53 * **************************************************************
54 */
55
56
57 /* Size of the errstr buffer needs to be MAXERROR */
58 static int
read_line(FILE * fp,char * buffer,int buflen,char * errstr)59 read_line(FILE *fp, char *buffer, int buflen, char *errstr)
60 {
61 int linelen;
62 char c;
63
64 *errstr = '\0';
65
66 for (linelen = 0; linelen < buflen; ) {
67 c = getc(fp);
68 if (c == EOF)
69 break;
70 switch (c) {
71 case '\n':
72 if (linelen > 0 && buffer[linelen - 1] == '\\') {
73 /* Continuation line found */
74 --linelen;
75 } else {
76 /* end of line found */
77 buffer[linelen] = '\0';
78 return (linelen);
79 }
80 break;
81 default:
82 buffer[linelen++] = c;
83 }
84 }
85
86 if (linelen >= buflen) {
87 (void) snprintf(errstr, MAXERROR,
88 gettext("Buffer overflow, line too long."));
89 return (-2);
90 } else if (linelen > 0 && buffer[linelen - 1] == '\\') {
91 (void) snprintf(errstr, MAXERROR,
92 gettext("Unterminated continuation line."));
93 return (-2);
94 } else {
95 /* end of file */
96 buffer[linelen] = '\0';
97 }
98 return (linelen > 0 ? linelen : -1);
99 }
100
101
102 static ns_parse_status
read_file(ns_config_t * ptr,int cred_file,ns_ldap_error_t ** error)103 read_file(ns_config_t *ptr, int cred_file, ns_ldap_error_t **error)
104 {
105 ParamIndexType i = 0;
106 char errstr[MAXERROR];
107 char buffer[BUFSIZE], *name, *value;
108 int emptyfile, lineno;
109 FILE *fp;
110 int ret;
111 int linelen;
112 char *file;
113 int first = 1;
114
115
116 if (cred_file) {
117 file = NSCREDFILE;
118 } else {
119 file = NSCONFIGFILE;
120 }
121 fp = fopen(file, "rF");
122 if (fp == NULL) {
123 (void) snprintf(errstr, sizeof (errstr),
124 gettext("Unable to open filename '%s' "
125 "for reading (errno=%d)."), file, errno);
126 MKERROR(LOG_ERR, *error, NS_CONFIG_FILE, strdup(errstr), NULL);
127 return (NS_NOTFOUND);
128 }
129
130 emptyfile = 1;
131 lineno = 0;
132 for (; ; ) {
133 if ((linelen = read_line(fp, buffer, sizeof (buffer),
134 errstr)) < 0)
135 /* End of file */
136 break;
137 lineno++;
138 if (linelen == 0)
139 continue;
140 /* get rid of comment lines */
141 if (buffer[0] == '#')
142 continue;
143 emptyfile = 0;
144 name = NULL;
145 value = NULL;
146 __s_api_split_key_value(buffer, &name, &value);
147 if (name == NULL || value == NULL) {
148 (void) snprintf(errstr, sizeof (errstr),
149 gettext("Missing Name or Value on line %d."),
150 lineno);
151 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
152 strdup(errstr), NULL);
153 (void) fclose(fp);
154 return (NS_PARSE_ERR);
155 }
156 if (__s_api_get_versiontype(ptr, name, &i) != 0) {
157 (void) snprintf(errstr, sizeof (errstr),
158 gettext("Illegal profile type on line %d."),
159 lineno);
160 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
161 strdup(errstr), NULL);
162 (void) fclose(fp);
163 return (NS_PARSE_ERR);
164 }
165 if (!first && i == NS_LDAP_FILE_VERSION_P) {
166 (void) snprintf(errstr, sizeof (errstr),
167 gettext("Illegal NS_LDAP_FILE_VERSION "
168 "on line %d."), lineno);
169 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
170 strdup(errstr), NULL);
171 (void) fclose(fp);
172 return (NS_PARSE_ERR);
173 }
174 first = 0;
175 switch (__s_api_get_configtype(i)) {
176 case SERVERCONFIG:
177 case CLIENTCONFIG:
178 if (cred_file == 0) {
179 ret = __ns_ldap_setParamValue(ptr, i, value,
180 error);
181 if (ret != NS_SUCCESS) {
182 (void) fclose(fp);
183 return (ret);
184 }
185 } else if (i != NS_LDAP_FILE_VERSION_P) {
186 (void) snprintf(errstr, sizeof (errstr),
187 gettext("Illegal entry in '%s' on "
188 "line %d"), file, lineno);
189 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
190 strdup(errstr), NULL);
191 (void) fclose(fp);
192 return (NS_PARSE_ERR);
193 }
194 break;
195 case CREDCONFIG:
196 if (i == NS_LDAP_FILE_VERSION_P)
197 break;
198 if (cred_file) {
199 ret = __ns_ldap_setParamValue(ptr, i, value,
200 error);
201 if (ret != NS_SUCCESS) {
202 (void) fclose(fp);
203 return (ret);
204 }
205 } else {
206 (void) snprintf(errstr, sizeof (errstr),
207 gettext("Illegal entry in '%s' on "
208 "line %d"), file, lineno);
209 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX,
210 strdup(errstr), NULL);
211 (void) fclose(fp);
212 return (NS_PARSE_ERR);
213 }
214 }
215 }
216 (void) fclose(fp);
217 if (!cred_file && emptyfile) {
218 /* Error in read_line */
219 (void) snprintf(errstr, sizeof (errstr),
220 gettext("Empty config file: '%s'"), file);
221 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
222 NULL);
223 return (NS_PARSE_ERR);
224 }
225 if (linelen == -2) {
226 /* Error in read_line */
227 (void) snprintf(errstr, sizeof (errstr),
228 gettext("Line too long in '%s'"), file);
229 MKERROR(LOG_ERR, *error, NS_CONFIG_SYNTAX, strdup(errstr),
230 NULL);
231 return (NS_PARSE_ERR);
232 }
233 return (NS_SUCCESS);
234 }
235
236
237 static
238 ns_ldap_return_code
set_attr(ns_config_t * config_struct,char * attr_name,char * attr_val,ns_ldap_error_t ** errorp)239 set_attr(ns_config_t *config_struct,
240 char *attr_name,
241 char *attr_val,
242 ns_ldap_error_t **errorp)
243 {
244 ParamIndexType idx;
245 char errmsg[MAXERROR];
246
247 if (errorp == NULL) {
248 return (NS_LDAP_INVALID_PARAM);
249 }
250
251 *errorp = NULL;
252
253 /*
254 * This double call is made due to the presence of
255 * two sets of LDAP config. attribute names.
256 * An LDAP configuration can be obtained either from a server
257 * or from SMF. The former sends a DUA with attributes' names
258 * styled like "preferredServerList". But local configurations
259 * will have names inherited from the /var/ldap/ldap* files such as
260 * "NS_LDAP_SERVER_PREF".
261 * So, the standalone bits are able to process both sets of
262 * attributes' names.
263 */
264 if (__s_api_get_profiletype(attr_name, &idx) < 0 &&
265 __s_api_get_versiontype(config_struct, attr_name, &idx) < 0) {
266 (void) snprintf(errmsg, sizeof (errmsg),
267 gettext("Illegal DUAProfile property: <%s>."), attr_name);
268 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
269 return (NS_LDAP_CONFIG);
270 }
271
272 return (__ns_ldap_setParamValue(config_struct, idx, attr_val, errorp));
273 }
274
275
276 /*
277 * This function creates a configuration which will be used
278 * for all LDAP requests in the Standalone mode.
279 *
280 * INPUT:
281 * config - a buffer returned by __ns_ldap_getConnectionInfo()'s
282 * dua_profile parameter.
283 *
284 */
285 ns_config_t *
__s_api_create_config_door_str(char * config,ns_ldap_error_t ** errorp)286 __s_api_create_config_door_str(char *config, ns_ldap_error_t **errorp)
287 {
288 char *attr, *attrName, *attrVal, *rest;
289 ns_config_t *configStruct = NULL;
290 char errmsg[MAXERROR];
291
292 if (config == NULL || errorp == NULL)
293 return (NULL);
294
295 if ((configStruct = __s_api_create_config()) == NULL) {
296 return (NULL);
297 }
298
299 *errorp = NULL;
300
301 attr = strtok_r(config, DOORLINESEP, &rest);
302 if (!attr) {
303 __s_api_destroy_config(configStruct);
304 (void) snprintf(errmsg, sizeof (errmsg),
305 gettext("DUAProfile received from the server"
306 " has bad format"));
307 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
308 return (NULL);
309 }
310
311 do {
312 __s_api_split_key_value(attr, &attrName, &attrVal);
313
314 if (attrName == NULL || attrVal == NULL) {
315 __s_api_destroy_config(configStruct);
316 (void) snprintf(errmsg, sizeof (errmsg),
317 gettext("Attribute %s is not valid"), attr);
318 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG,
319 strdup(errmsg), NULL);
320 return (NULL);
321 }
322
323 /* Get the version of the profile. */
324 if (strcasecmp(attrName, "objectclass") == 0) {
325 if (strcasecmp(attrVal, _PROFILE2_OBJECTCLASS) == 0) {
326 if (__ns_ldap_setParamValue(configStruct,
327 NS_LDAP_FILE_VERSION_P,
328 NS_LDAP_VERSION_2,
329 errorp) != NS_LDAP_SUCCESS) {
330 __s_api_destroy_config(configStruct);
331 return (NULL);
332 }
333 } else if (strcasecmp(attrVal,
334 _PROFILE1_OBJECTCLASS) == 0) {
335 if (__ns_ldap_setParamValue(configStruct,
336 NS_LDAP_FILE_VERSION_P,
337 NS_LDAP_VERSION_1,
338 errorp) != NS_LDAP_SUCCESS) {
339 __s_api_destroy_config(configStruct);
340 return (NULL);
341 }
342 }
343 continue;
344 }
345
346 if (set_attr(configStruct, attrName, attrVal, errorp) !=
347 NS_LDAP_SUCCESS) {
348 __s_api_destroy_config(configStruct);
349 return (NULL);
350 }
351 } while (attr = strtok_r(NULL, DOORLINESEP, &rest));
352
353 if (__s_api_crosscheck(configStruct, errmsg, B_FALSE) != NS_SUCCESS) {
354 MKERROR(LOG_ERR, *errorp, NS_LDAP_CONFIG, strdup(errmsg), NULL);
355 __s_api_destroy_config(configStruct);
356 return (NULL);
357 }
358
359 return (configStruct);
360 }
361
362
363 /*
364 * Cache Manager side of configuration file loading
365 */
366
367 ns_ldap_error_t *
__ns_ldap_LoadConfiguration()368 __ns_ldap_LoadConfiguration()
369 {
370 ns_ldap_error_t *error = NULL;
371 ns_config_t *ptr = NULL;
372 char errstr[MAXERROR];
373 ns_parse_status ret;
374
375
376 ptr = __s_api_create_config();
377 if (ptr == NULL) {
378 (void) snprintf(errstr, sizeof (errstr),
379 gettext("__ns_ldap_LoadConfiguration: Out of memory."));
380 MKERROR(LOG_ERR, error, NS_CONFIG_NOTLOADED,
381 strdup(errstr), NULL);
382 return (error);
383 }
384
385 /* Load in Configuration file */
386 ret = read_file(ptr, 0, &error);
387 if (ret != NS_SUCCESS) {
388 __s_api_destroy_config(ptr);
389 return (error);
390 }
391
392 /* Load in Credential file */
393 ret = read_file(ptr, 1, &error);
394 if (ret != NS_SUCCESS) {
395 __s_api_destroy_config(ptr);
396 return (error);
397 }
398
399 if (__s_api_crosscheck(ptr, errstr, B_TRUE) != NS_SUCCESS) {
400 __s_api_destroy_config(ptr);
401 MKERROR(LOG_ERR, error, NS_CONFIG_SYNTAX, strdup(errstr), NULL);
402 return (error);
403 }
404
405 __s_api_init_config(ptr);
406 return (NULL);
407 }
408
409
410 int
__print2buf(LineBuf * line,const char * toprint,char * sep)411 __print2buf(LineBuf *line, const char *toprint, char *sep)
412 {
413 int newsz = 0;
414 int newmax = 0;
415 char *str;
416
417 if (line == NULL)
418 return (-1);
419
420 newsz = strlen(toprint) + line->len + 1;
421 if (sep != NULL) {
422 newsz += strlen(sep);
423 }
424 if (line->alloc == 0 || newsz > line->alloc) {
425 /* Round up to next buffer and add 1 */
426 newmax = (((newsz+(BUFSIZ-1))/BUFSIZ)+1) * BUFSIZ;
427 if (line->alloc == 0)
428 line->str = (char *)calloc(newmax, 1);
429 else {
430 /*
431 * if realloc() returns NULL,
432 * the original buffer is untouched.
433 * It needs to be freed.
434 */
435 str = (char *)realloc(line->str, newmax);
436 if (str == NULL) {
437 free(line->str);
438 line->str = NULL;
439 }
440 else
441 line->str = str;
442 }
443 line->alloc = newmax;
444 if (line->str == NULL) {
445 line->alloc = 0;
446 line->len = 0;
447 return (-1);
448 }
449 }
450 /* now add new 'toprint' data to buffer */
451 (void) strlcat(line->str, toprint, line->alloc);
452 if (sep != NULL) {
453 (void) strlcat(line->str, sep, line->alloc);
454 }
455 line->len = newsz;
456 return (0);
457 }
458
459
460 /*
461 * __ns_ldap_LoadDoorInfo is a routine used by the ldapcachemgr
462 * to create a configuration buffer to transmit back to a client
463 * domainname is transmitted to ldapcachemgr and ldapcachemgr uses
464 * it to select a configuration to transmit back. Otherwise it
465 * is essentially unused in sldap.
466 * If cred_only is not 0, then only the credentials for shadow
467 * update are taken care of.
468 */
469
470 ns_ldap_error_t *
__ns_ldap_LoadDoorInfo(LineBuf * configinfo,char * domainname,ns_config_t * new,int cred_only)471 __ns_ldap_LoadDoorInfo(LineBuf *configinfo, char *domainname,
472 ns_config_t *new, int cred_only)
473 {
474 ns_config_t *ptr;
475 char errstr[MAXERROR];
476 ns_ldap_error_t *errorp;
477 char *str;
478 ParamIndexType i = 0;
479 int len;
480 ldap_config_out_t *cout;
481
482 /*
483 * If new is NULL, it outputs the flatten data of current default
484 * config, if it's non-NULL, it outputs the flatten data of a temporary
485 * config. It's used to compare the new config data with the current
486 * default config data.
487 */
488 if (new == NULL)
489 ptr = __s_api_get_default_config();
490 else
491 ptr = new;
492 if (ptr == NULL) {
493 (void) snprintf(errstr, sizeof (errstr),
494 gettext("No configuration information available for %s."),
495 domainname == NULL ? "<no domain specified>" : domainname);
496 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
497 strdup(errstr), NULL);
498 return (errorp);
499 }
500 (void) memset((char *)configinfo, 0, sizeof (LineBuf));
501 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
502 if (cred_only) {
503 /* only exposed credential for shadow update */
504 if (i != NS_LDAP_ADMIN_BINDDN_P &&
505 i != NS_LDAP_ADMIN_BINDPASSWD_P)
506 continue;
507 } else {
508 /* credential for shadow update is not to be exposed */
509 if (i == NS_LDAP_ADMIN_BINDDN_P ||
510 i == NS_LDAP_ADMIN_BINDPASSWD_P)
511 continue;
512 }
513 str = __s_api_strValue(ptr, i, NS_DOOR_FMT);
514 if (str == NULL)
515 continue;
516 if (__print2buf(configinfo, str, DOORLINESEP)) {
517 (void) snprintf(errstr, sizeof (errstr),
518 gettext("__print2buf: Out of memory."));
519 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
520 strdup(errstr), NULL);
521 __s_api_release_config(ptr);
522 free(str);
523 return (errorp);
524 }
525 free(str);
526 }
527 if (new == NULL)
528 __s_api_release_config(ptr);
529
530 /*
531 * The new interface of the configuration between ldap_cachemgr
532 * & libsldap contains a header structure ldap_config_out_t.
533 * The flatten configuration data configinfo->str is cloned
534 * to cout->config_str, configinfo->len is saved in
535 * cout->data_size and cout->cookie is set later after this function
536 * is returned in ldap_cachemgr.
537 * configinfo->str & configinfo->len are reused to save info of
538 * header + data.
539 * The format:
540 * [cookie|data_size|config_str .............]
541 */
542
543 if (configinfo->str) {
544 len = sizeof (ldap_config_out_t) - sizeof (int) +
545 configinfo->len;
546 if ((cout = calloc(1, len)) == NULL) {
547 free(configinfo->str);
548 configinfo->str = NULL;
549 configinfo->len = 0;
550 (void) snprintf(errstr, sizeof (errstr),
551 gettext("calloc: Out of memory."));
552 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
553 strdup(errstr), NULL);
554 return (errorp);
555 }
556 /*
557 * cout->cookie is set by the caller,
558 * which is in ldap_cachemgr.
559 */
560 cout->data_size = configinfo->len;
561 (void) memcpy(cout->config_str, configinfo->str,
562 configinfo->len);
563 free(configinfo->str);
564 configinfo->str = (char *)cout;
565 configinfo->len = len;
566 }
567 return (NULL);
568 }
569
570
571 ns_ldap_error_t *
__ns_ldap_DumpLdif(char * filename)572 __ns_ldap_DumpLdif(char *filename)
573 {
574 ns_config_t *ptr;
575 char errstr[MAXERROR];
576 ns_ldap_error_t *errorp;
577 char *str;
578 FILE *fp;
579 ParamIndexType i = 0;
580 char *profile, *container, *base;
581
582 ptr = __s_api_get_default_config();
583 if (ptr == NULL) {
584 (void) snprintf(errstr, sizeof (errstr),
585 gettext("No configuration information available."));
586 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
587 NULL);
588 return (errorp);
589 }
590
591 if (filename == NULL) {
592 fp = stdout;
593 } else {
594 fp = fopen(filename, "wF");
595 if (fp == NULL) {
596 (void) snprintf(errstr, sizeof (errstr),
597 gettext("Unable to open filename %s for ldif "
598 "dump (errno=%d)."), filename, errno);
599 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE,
600 strdup(errstr), NULL);
601 __s_api_release_config(ptr);
602 return (errorp);
603 }
604 (void) fchmod(fileno(fp), 0444);
605 }
606
607 if (ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_ptype != CHARPTR ||
608 ptr->paramList[NS_LDAP_PROFILE_P].ns_ptype != CHARPTR) {
609 (void) snprintf(errstr, sizeof (errstr),
610 gettext("Required BaseDN and/or Profile name "
611 "ldif fields not present"));
612 MKERROR(LOG_WARNING, errorp, NS_CONFIG_FILE, strdup(errstr),
613 NULL);
614 __s_api_release_config(ptr);
615 return (errorp);
616 }
617
618 profile = ptr->paramList[NS_LDAP_PROFILE_P].ns_pc;
619 base = ptr->paramList[NS_LDAP_SEARCH_BASEDN_P].ns_pc;
620 container = _PROFILE_CONTAINER;
621
622 /*
623 * Construct DN, but since this is the profile, there is no need
624 * to worry about mapping. The profile itself can not be mapped
625 */
626 (void) fprintf(fp, "dn: cn=%s,ou=%s,%s\n", profile, container, base);
627
628 /* dump objectclass names */
629 if (ptr->version == NS_LDAP_V1) {
630 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
631 _PROFILE1_OBJECTCLASS);
632 } else {
633 (void) fprintf(fp, "ObjectClass: top\nObjectClass: %s\n",
634 _PROFILE2_OBJECTCLASS);
635 }
636
637 /* For each parameter - construct value */
638 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
639 str = __s_api_strValue(ptr, i, NS_LDIF_FMT);
640 if (str == NULL)
641 continue;
642 /*
643 * don't dump binddn, bind password, admin binddn, admin
644 * bind password, enableShadowUpdate flag, or cert path
645 * as they are not part of version 2 profiles
646 */
647 if ((i != NS_LDAP_BINDDN_P) &&
648 (i != NS_LDAP_BINDPASSWD_P) &&
649 (i != NS_LDAP_ADMIN_BINDDN_P) &&
650 (i != NS_LDAP_ADMIN_BINDPASSWD_P) &&
651 (i != NS_LDAP_ENABLE_SHADOW_UPDATE_P) &&
652 (i != NS_LDAP_HOST_CERTPATH_P))
653 (void) fprintf(fp, "%s\n", str);
654 free(str);
655 }
656
657 if (filename != NULL)
658 (void) fclose(fp);
659
660 __s_api_release_config(ptr);
661 return (NULL);
662 }
663
664 /*
665 * This routine can process the configuration and/or
666 * the credential files at the same time.
667 * files is char *[3] = { "config", "cred", NULL };
668 */
669
670 static
671 ns_ldap_error_t *
__ns_ldap_DumpConfigFiles(char ** files)672 __ns_ldap_DumpConfigFiles(char **files)
673 {
674 char *filename;
675 int fi;
676 int docred;
677 ns_config_t *ptr;
678 char *str;
679 char errstr[MAXERROR];
680 ParamIndexType i = 0;
681 FILE *fp;
682 int rc;
683 ns_ldap_error_t *errorp = NULL;
684 struct stat buf;
685 int cfgtype;
686 boolean_t file_export_error = B_FALSE;
687
688 ptr = __s_api_get_default_config();
689 if (ptr == NULL) {
690 (void) snprintf(errstr, sizeof (errstr),
691 gettext("No configuration information available."));
692 MKERROR(LOG_ERR, errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
693 NULL);
694 return (errorp);
695 }
696
697 for (fi = 0; fi < 2; fi++) {
698 docred = 0;
699 filename = files[fi];
700 if (filename == NULL)
701 continue;
702 if (fi == 1)
703 docred++;
704 rc = stat(filename, &buf);
705 fp = fopen(filename, "wF");
706 if (fp == NULL) {
707 (void) snprintf(errstr, sizeof (errstr),
708 gettext("Unable to open filename %s"
709 " for configuration dump (%s)."),
710 filename, strerror(errno));
711 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
712 strdup(errstr), NULL);
713 __s_api_release_config(ptr);
714 return (errorp);
715 }
716 if (rc == 0) {
717 if (fchmod(fileno(fp), buf.st_mode) != 0) {
718 (void) snprintf(errstr, sizeof (errstr),
719 gettext("Unable to set permissions for file"
720 " %s for configuration dump (%s)."),
721 filename, strerror(errno));
722 (void) fclose(fp);
723 file_export_error = B_TRUE;
724 break;
725 }
726 } else {
727 if (fchmod(fileno(fp), 0400) != 0) {
728 (void) snprintf(errstr, sizeof (errstr),
729 gettext("Unable to set permissions for file"
730 " %s for configuration dump (%s)."),
731 filename, strerror(errno));
732 (void) fclose(fp);
733 file_export_error = B_TRUE;
734 break;
735 }
736 }
737 if (fprintf(fp, "#\n# %s\n#\n", DONOTEDIT) < 0) {
738 (void) snprintf(errstr, sizeof (errstr), gettext(
739 "Writing to file %s for configuration dump failed "
740 "(%s)."), filename, strerror(errno));
741 file_export_error = B_TRUE;
742 }
743
744 /* assume VERSION is set and it outputs first */
745
746 /* For each parameter - construct value */
747 for (i = 0; !file_export_error && (i <= NS_LDAP_MAX_PIT_P);
748 i++) {
749 cfgtype = __s_api_get_configtype(i);
750 if ((docred == 0 && cfgtype == CREDCONFIG) ||
751 (docred == 1 && cfgtype != CREDCONFIG))
752 continue;
753
754 str = __s_api_strValue(ptr, i, NS_FILE_FMT);
755 if (str == NULL)
756 continue;
757 if (fprintf(fp, "%s\n", str) < 0) {
758 (void) snprintf(errstr, sizeof (errstr),
759 gettext("Writing to file %s for"
760 "configuration dump failed (%s)."),
761 filename, strerror(errno));
762 file_export_error = B_TRUE;
763 }
764
765 free(str);
766 }
767 if (fclose(fp) != 0) {
768 /* Break if error already hit */
769 if (file_export_error)
770 break;
771
772 (void) snprintf(errstr, sizeof (errstr), gettext(
773 "Writing to file %s for configuration dump failed "
774 "during file close (%s)."), filename,
775 strerror(errno));
776 file_export_error = B_TRUE;
777 break;
778 }
779
780 }
781
782 if (file_export_error) {
783 MKERROR(LOG_ERR, errorp, NS_CONFIG_FILE,
784 strdup(errstr), NULL);
785 (void) unlink(filename);
786 }
787
788 __s_api_release_config(ptr);
789 return (errorp);
790 }
791
792 ns_ldap_error_t *
__ns_ldap_DumpConfiguration(char * file)793 __ns_ldap_DumpConfiguration(char *file)
794 {
795 ns_ldap_error_t *ret;
796 char *files[3];
797
798 files[0] = NULL;
799 files[1] = NULL;
800 files[2] = NULL;
801 if (strcmp(file, NSCONFIGFILE) == 0) {
802 files[0] = file;
803 } else if (strcmp(file, NSCONFIGREFRESH) == 0) {
804 files[0] = file;
805 } else if (strcmp(file, NSCREDFILE) == 0) {
806 files[1] = file;
807 } else if (strcmp(file, NSCREDREFRESH) == 0) {
808 files[1] = file;
809 }
810 ret = __ns_ldap_DumpConfigFiles(files);
811 return (ret);
812 }
813
814 /*
815 * **************************************************************
816 * Misc Routines
817 * **************************************************************
818 */
819
820 ns_config_t *
__ns_ldap_make_config(ns_ldap_result_t * result)821 __ns_ldap_make_config(ns_ldap_result_t *result)
822 {
823 int l, m;
824 char val[BUFSIZE];
825 char *attrname;
826 ns_ldap_entry_t *entry;
827 ns_ldap_attr_t *attr;
828 char **attrval;
829 ParamIndexType index;
830 ns_config_t *ptr;
831 ns_ldap_error_t *error = NULL;
832 int prof_ver;
833 ns_config_t *curr_ptr = NULL;
834 char errstr[MAXERROR];
835 ns_ldap_error_t *errorp;
836 LineBuf buffer;
837 char *sepstr;
838
839 if (result == NULL)
840 return (NULL);
841
842 if (result->entries_count > 1) {
843 (void) snprintf(errstr, MAXERROR,
844 gettext("Configuration Error: More than one profile "
845 "found"));
846 MKERROR(LOG_ERR, errorp, NS_PARSE_ERR, strdup(errstr), NULL);
847 (void) __ns_ldap_freeError(&errorp);
848 return (NULL);
849 }
850
851 ptr = __s_api_create_config();
852 if (ptr == NULL)
853 return (NULL);
854
855 curr_ptr = __s_api_get_default_config();
856 if (curr_ptr == NULL) {
857 __s_api_destroy_config(ptr);
858 return (NULL);
859 }
860
861 /* Check to see if the profile is version 1 or version 2 */
862 prof_ver = 1;
863 entry = result->entry;
864 for (l = 0; l < entry->attr_count; l++) {
865 attr = entry->attr_pair[l];
866
867 attrname = attr->attrname;
868 if (attrname == NULL)
869 continue;
870 if (strcasecmp(attrname, "objectclass") == 0) {
871 for (m = 0; m < attr->value_count; m++) {
872 if (strcasecmp(_PROFILE2_OBJECTCLASS,
873 attr->attrvalue[m]) == 0) {
874 prof_ver = 2;
875 break;
876 }
877 }
878 }
879 }
880 /* update the configuration to accept v1 or v2 attributes */
881 if (prof_ver == 1) {
882 (void) strcpy(val, NS_LDAP_VERSION_1);
883 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
884 val, &error);
885 } else {
886 (void) strcpy(val, NS_LDAP_VERSION_2);
887 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_FILE_VERSION_P,
888 val, &error);
889 }
890
891 for (l = 0; l < entry->attr_count; l++) {
892 attr = entry->attr_pair[l];
893
894 attrname = attr->attrname;
895 if (attrname == NULL)
896 continue;
897 if (__s_api_get_profiletype(attrname, &index) != 0)
898 continue;
899
900 attrval = attr->attrvalue;
901 switch (index) {
902 case NS_LDAP_SEARCH_DN_P:
903 case NS_LDAP_SERVICE_SEARCH_DESC_P:
904 case NS_LDAP_ATTRIBUTEMAP_P:
905 case NS_LDAP_OBJECTCLASSMAP_P:
906 case NS_LDAP_SERVICE_CRED_LEVEL_P:
907 case NS_LDAP_SERVICE_AUTH_METHOD_P:
908 /* Multiple Value - insert 1 at a time */
909 for (m = 0; m < attr->value_count; m++) {
910 (void) __ns_ldap_setParamValue(ptr, index,
911 attrval[m], &error);
912 }
913 break;
914 default:
915 (void) memset((void *)&buffer, 0, sizeof (LineBuf));
916
917 /* Single or Multiple Value */
918 for (m = 0; m < attr->value_count; m++) {
919 sepstr = NULL;
920 if (m != attr->value_count - 1) {
921 sepstr = SPACESEP;
922 }
923 if (__print2buf(&buffer, attrval[m], sepstr))
924 goto makeconfigerror;
925 }
926 (void) __ns_ldap_setParamValue(ptr, index, buffer.str,
927 &error);
928 if (buffer.len > 0) {
929 free(buffer.str);
930 buffer.len = 0;
931 }
932 break;
933 }
934 }
935 if (ptr->version != NS_LDAP_V1) {
936 ParamIndexType i;
937 if (curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_ptype == CHARPTR) {
938 (void) __ns_ldap_setParamValue(ptr, NS_LDAP_BINDDN_P,
939 curr_ptr->paramList[NS_LDAP_BINDDN_P].ns_pc,
940 &error);
941 }
942 if (curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_ptype ==
943 CHARPTR) {
944 (void) __ns_ldap_setParamValue(ptr,
945 NS_LDAP_BINDPASSWD_P,
946 curr_ptr->paramList[NS_LDAP_BINDPASSWD_P].ns_pc,
947 &error);
948 }
949 i = NS_LDAP_ENABLE_SHADOW_UPDATE_P;
950 if (curr_ptr->paramList[i].ns_ptype == INT) {
951 char *valt;
952 valt = __s_get_shadowupdate_name(
953 curr_ptr->paramList[i].ns_i);
954 (void) __ns_ldap_setParamValue(ptr, i, valt, &error);
955 }
956 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_ptype ==
957 CHARPTR) {
958 (void) __ns_ldap_setParamValue(ptr,
959 NS_LDAP_ADMIN_BINDDN_P,
960 curr_ptr->paramList[NS_LDAP_ADMIN_BINDDN_P].ns_pc,
961 &error);
962 }
963 if (curr_ptr->paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_ptype ==
964 CHARPTR) {
965 (void) __ns_ldap_setParamValue(ptr,
966 NS_LDAP_ADMIN_BINDPASSWD_P,
967 curr_ptr->
968 paramList[NS_LDAP_ADMIN_BINDPASSWD_P].ns_pc,
969 &error);
970 }
971 if (curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_ptype ==
972 CHARPTR) {
973 (void) __ns_ldap_setParamValue(ptr,
974 NS_LDAP_HOST_CERTPATH_P,
975 curr_ptr->paramList[NS_LDAP_HOST_CERTPATH_P].ns_pc,
976 &error);
977 }
978 }
979 __s_api_release_config(curr_ptr);
980 return (ptr);
981
982 makeconfigerror:
983 if (buffer.len > 0)
984 free(buffer.str);
985
986 __s_api_debug_pause(LOG_ERR, NS_PARSE_ERR,
987 "__ns_ldap_make_config: Not enough memory");
988 return (NULL);
989 }
990
991 /*
992 * Download a profile into our internal structure. The calling application
993 * needs to DumpConfig() to save the information to NSCONFIGFILE and NSCREDFILE
994 * if desired.
995 */
996 int
__ns_ldap_download(const char * profile,char * addr,char * baseDN,ns_ldap_error_t ** errorp)997 __ns_ldap_download(const char *profile, char *addr, char *baseDN,
998 ns_ldap_error_t **errorp)
999 {
1000 char filter[BUFSIZE];
1001 int rc;
1002 ns_ldap_result_t *result = NULL;
1003 ns_config_t *ptr = NULL;
1004 ns_config_t *new_ptr = NULL;
1005 char errstr[MAXERROR];
1006
1007 *errorp = NULL;
1008 if (baseDN == NULL)
1009 return (NS_LDAP_INVALID_PARAM);
1010
1011 ptr = __s_api_get_default_config();
1012 if (ptr == NULL) {
1013 (void) snprintf(errstr, sizeof (errstr),
1014 gettext("No configuration information available."));
1015 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
1016 NULL);
1017 return (NS_LDAP_CONFIG);
1018 }
1019
1020 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SEARCH_BASEDN_P, baseDN,
1021 errorp);
1022 if (rc != NS_LDAP_SUCCESS) {
1023 __s_api_release_config(ptr);
1024 return (rc);
1025 }
1026
1027 rc = __ns_ldap_setParamValue(ptr, NS_LDAP_SERVERS_P, addr, errorp);
1028 __s_api_release_config(ptr);
1029 if (rc != NS_LDAP_SUCCESS)
1030 return (rc);
1031
1032 (void) snprintf(filter, sizeof (filter), _PROFILE_FILTER,
1033 _PROFILE1_OBJECTCLASS, _PROFILE2_OBJECTCLASS, profile);
1034 rc = __ns_ldap_list(_PROFILE_CONTAINER, (const char *)filter,
1035 NULL, NULL, NULL, 0, &result, errorp, NULL, NULL);
1036
1037 if (rc != NS_LDAP_SUCCESS)
1038 return (rc);
1039
1040 new_ptr = __ns_ldap_make_config(result);
1041 (void) __ns_ldap_freeResult(&result);
1042
1043 if (new_ptr == NULL)
1044 return (NS_LDAP_OP_FAILED);
1045
1046 rc = __s_api_crosscheck(new_ptr, errstr, B_FALSE);
1047 if (rc != NS_LDAP_SUCCESS) {
1048 __s_api_destroy_config(new_ptr);
1049 MKERROR(LOG_ERR, *errorp, NS_CONFIG_NOTLOADED, strdup(errstr),
1050 NULL);
1051 return (NS_LDAP_CONFIG);
1052 }
1053
1054 __s_api_init_config(new_ptr);
1055 return (rc);
1056 }
1057
1058 /*
1059 * **************************************************************
1060 * Configuration Printing Routines
1061 * **************************************************************
1062 */
1063
1064 /*
1065 * Yes the use of stdio is okay here because all we are doing is sending
1066 * output to stdout. This would not be necessary if we could get to the
1067 * configuration pointer outside this file.
1068 */
1069 ns_ldap_error_t *
__ns_ldap_print_config(int verbose)1070 __ns_ldap_print_config(int verbose)
1071 {
1072 ns_config_t *ptr;
1073 char errstr[MAXERROR];
1074 ns_ldap_error_t *errorp;
1075 char *str;
1076 int i;
1077
1078 ptr = __s_api_get_default_config();
1079 if (ptr == NULL) {
1080 errorp = __ns_ldap_LoadConfiguration();
1081 if (errorp != NULL)
1082 return (errorp);
1083 ptr = __s_api_get_default_config();
1084 if (ptr == NULL) {
1085 (void) snprintf(errstr, sizeof (errstr),
1086 gettext("No configuration information."));
1087 MKERROR(LOG_WARNING, errorp, NS_CONFIG_NOTLOADED,
1088 strdup(errstr), NULL);
1089 return (errorp);
1090 }
1091 }
1092
1093 if (verbose && (ptr->domainName != NULL)) {
1094 (void) fputs("ptr->domainName ", stdout);
1095 (void) fputs(ptr->domainName, stdout);
1096 (void) putchar('\n');
1097 }
1098 /* For each parameter - construct value */
1099 for (i = 0; i <= NS_LDAP_MAX_PIT_P; i++) {
1100 /*
1101 * Version 1 skipped this entry because:
1102 *
1103 * don't print default cache TTL for now since
1104 * we don't store it in the ldap_client_file.
1105 */
1106 if ((i == NS_LDAP_CACHETTL_P) && (ptr->version == NS_LDAP_V1))
1107 continue;
1108
1109 /* the credential for shadow update is not to be exposed */
1110 if (i == NS_LDAP_ADMIN_BINDDN_P ||
1111 i == NS_LDAP_ADMIN_BINDPASSWD_P)
1112 continue;
1113
1114 str = __s_api_strValue(ptr, i, NS_FILE_FMT);
1115 if (str == NULL)
1116 continue;
1117 if (verbose)
1118 (void) putchar('\t');
1119 (void) fprintf(stdout, "%s\n", str);
1120 free(str);
1121 }
1122
1123 __s_api_release_config(ptr);
1124 return (NULL);
1125 }
1126