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 * Copyright 2012 Milan Jurik. All rights reserved.
25 */
26
27 /*
28 * ldapclient command. To make (initiailize) or uninitialize a machines as
29 * and LDAP client. This command MUST be run as root (or it will simply exit).
30 *
31 * -I Install. No file_backup/recover for installing only (no doc).
32 *
33 * init Initialze (create) an LDAP client from a profile stored
34 * in a directory-server.
35 * manual Initialze (create) an LDAP client by hand (-file option
36 * reads from file).
37 * mod Modify the LDAP client configuration on this machine by hand.
38 * list List the contents of the LDAP client cache files.
39 * uninit Uninitialize this machine.
40 *
41 * -v Verbose flag.
42 * -q Quiet flag (mutually exclusive with -v).
43 *
44 * -a attrName=attrVal
45 * <attrName> can be one of the following:
46 *
47 * attributeMap
48 * Attribute map. Can be multiple instances of this option.
49 * (no former option)
50 * authenticationMethod
51 * Authentication method (formerly -a)
52 * bindTimeLimit
53 * Bind time limit. (no former option)
54 * certificatePath
55 * Path to certificates used for secure bind (no former option)
56 * credentialLevel
57 * Client credential level (no former option)
58 * defaultServerList
59 * Default server (no former option) Refer to DUA Config
60 * Schema draft.
61 * defaultSearchBase
62 * Search Base DN. e.g. dc=eng,dc=sun,dc=com (formerly -b)
63 * defaultSearchScope
64 * Search scope. (formerly -s)
65 * domainName
66 * Hosts lookup domain (DNS) Ex. eng.sun.com (formerly -d)
67 * followReferrals
68 * Search dereference. followref or noref (default followref)
69 * (formerly -r)
70 * objectclassMap
71 * Objectclass map. Can be multiple instances of this option.
72 * (no former option)
73 * preferredServerList
74 * Server preference list. Comma ',' seperated list of IPaddr.
75 * (formerly -p)
76 * profileName
77 * Profile name to use for init (ldapclient) or
78 * generate (gen_profile). (formerly -P)
79 * profileTTL
80 * Client info TTL. If set to 0 this information will not be
81 * automatically updated by the ldap_cachemgr(1M).
82 * (formerly -e)
83 * proxyDN
84 * Binding DN. Ex. cn=client,ou=people,cd=eng,dc=sun,dc=com
85 * (formerly -D)
86 * proxyPassword
87 * Client password not needed for authentication "none".
88 * (formerly -w)
89 * adminDN
90 * Administrator DN for updating naming data.
91 * adminPassword
92 * Administrator password
93 * enableShadowUpdate
94 * Allow Administrator to change shadow data in LDAP
95 * searchTimeLimit
96 * Timeout value. (formerly -o)
97 * serviceSearchDescriptor
98 * Service search scope. (no former option)
99 * serviceAuthenticationMethod
100 * Service authenticaion method (no former option)
101 * serviceCredentialLevel
102 * Service credential level (no former option)
103 *
104 */
105
106 #include <stdlib.h>
107 #include <stdio.h>
108 #include <unistd.h>
109 #include <errno.h>
110 #include <sys/types.h>
111 #include <time.h>
112 #include <sys/param.h>
113 #include <sys/stat.h>
114 #include <sys/systeminfo.h>
115 #include <fcntl.h>
116 #include <xti.h>
117 #include <strings.h>
118 #include <limits.h>
119 #include <locale.h>
120 #include <syslog.h>
121 #include <libscf.h>
122 #include <assert.h>
123
124 #include "standalone.h"
125
126 #if !defined(TEXT_DOMAIN)
127 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
128 #endif
129
130 /* error codes */
131 /* The manpage doc only allows for SUCCESS(0), FAIL(1) and CRED(2) on exit */
132 #define CLIENT_SUCCESS 0
133 #define CLIENT_ERR_PARSE -1
134 #define CLIENT_ERR_FAIL 1
135 #define CLIENT_ERR_CREDENTIAL 2
136 #define CLIENT_ERR_MEMORY 3
137 #define CLIENT_ERR_RESTORE 4
138 #define CLIENT_ERR_RENAME 5
139 #define CLIENT_ERR_RECOVER 6
140 #define CLIENT_ERR_TIMEDOUT 7
141 #define CLIENT_ERR_MAINTENANCE 8
142
143 /* Reset flag for start_services() */
144 #define START_INIT 1
145 #define START_RESET 2
146 #define START_UNINIT 3
147
148 /* Reset flag for stop_services() */
149 #define STATE_NOSAVE 0
150 #define STATE_SAVE 1
151
152 /* files to (possibiliy) restore */
153 #define LDAP_RESTORE_DIR "/var/ldap/restore"
154
155 #define DOMAINNAME_DIR "/etc"
156 #define DOMAINNAME_FILE "defaultdomain"
157 #define DOMAINNAME DOMAINNAME_DIR "/" DOMAINNAME_FILE
158 #define DOMAINNAME_BACK LDAP_RESTORE_DIR "/" DOMAINNAME_FILE
159
160 #define NSSWITCH_DIR "/etc"
161 #define NSSWITCH_FILE "nsswitch.conf"
162 #define NSSWITCH_CONF NSSWITCH_DIR "/" NSSWITCH_FILE
163 #define NSSWITCH_BACK LDAP_RESTORE_DIR "/" NSSWITCH_FILE
164 #define NSSWITCH_LDAP "/etc/nsswitch.ldap"
165
166 #define YP_BIND_DIR "/var/yp/binding"
167
168 /* Define the service FMRIs */
169 #define SENDMAIL_FMRI "network/smtp:sendmail"
170 #define NSCD_FMRI "system/name-service-cache:default"
171 #define AUTOFS_FMRI "system/filesystem/autofs:default"
172 #define LDAP_FMRI "network/ldap/client:default"
173 #define YP_FMRI "network/nis/client:default"
174 #define NS_MILESTONE_FMRI "milestone/name-services:default"
175
176 /* Define flags for checking if services were enabled */
177 #define SENDMAIL_ON 0x1
178 #define NSCD_ON 0x10
179 #define AUTOFS_ON 0x100
180
181 #define CMD_DOMAIN_START "/usr/bin/domainname"
182
183 /* Command to copy files */
184 #define CMD_CP "/bin/cp -f"
185 #define CMD_MV "/bin/mv -f"
186 #define CMD_RM "/bin/rm -f"
187
188 #define TO_DEV_NULL " >/dev/null 2>&1"
189
190 /* Files that need to be just removed */
191 #define LDAP_CACHE_LOG "/var/ldap/cachemgr.log"
192
193 /* Output defines to supress if quiet mode set */
194 #define CLIENT_FPUTS if (!mode_quiet) (void) fputs
195 #define CLIENT_FPRINTF if (!mode_quiet) (void) fprintf
196 #define CLIENT_FPUTC if (!mode_quiet) (void) fputc
197
198 #define restart_service(fmri, waitflag)\
199 do_service(fmri, waitflag, RESTART_SERVICE,\
200 SCF_STATE_STRING_ONLINE)
201 #define start_service(fmri, waitflag) \
202 do_service(fmri, waitflag, START_SERVICE,\
203 SCF_STATE_STRING_ONLINE)
204 #define disable_service(fmri, waitflag) \
205 do_service(fmri, waitflag, STOP_SERVICE,\
206 SCF_STATE_STRING_DISABLED)
207
208 /*
209 * There isn't a domainName defined as a param, so we set a value here
210 * (1001) should be big enough
211 */
212 #define LOCAL_DOMAIN_P 1001
213
214 #define START_SERVICE 1
215 #define STOP_SERVICE 2
216 #define RESTART_SERVICE 3
217
218 #define DEFAULT_TIMEOUT 60000000
219
220 #define INIT_WAIT_USECS 50000
221
222 /* Used to turn off profile checking */
223 #define CACHETTL_OFF "0"
224
225 /* Globals */
226 static char *cmd;
227
228 static char *dname = NULL;
229 static char dname_buf[BUFSIZ];
230
231 static boolean_t sysid_install = B_FALSE;
232
233 static int mode_verbose = 0;
234 static int mode_quiet = 0;
235 static int gen = 0;
236
237 static int gStartLdap = 0;
238 static int gStartYp = 0;
239
240 static int enableFlag = 0;
241
242 /* multival_t is used to hold params that can have more than one value */
243 typedef struct {
244 int count;
245 char **optlist;
246 } multival_t;
247
248 static multival_t *multival_new();
249 static int multival_add(multival_t *list, char *opt);
250 static void multival_free(multival_t *list);
251
252 /*
253 * clientopts_t is used to hold and pass around the param values from
254 * the cmd line
255 */
256 typedef struct {
257 multival_t *attributeMap;
258 char *authenticationMethod;
259 char *bindTimeLimit;
260 char *certificatePath;
261 char *credentialLevel;
262 char *defaultSearchBase;
263 char *defaultServerList;
264 char *domainName;
265 char *followReferrals;
266 multival_t *objectclassMap;
267 char *preferredServerList;
268 char *profileName;
269 char *profileTTL;
270 char *proxyDN;
271 char *proxyPassword;
272 char *enableShadowUpdate;
273 char *adminDN;
274 char *adminPassword;
275 char *bindDN;
276 char *bindPasswd;
277 char *defaultSearchScope;
278 char *searchTimeLimit;
279 multival_t *serviceAuthenticationMethod;
280 multival_t *serviceCredentialLevel;
281 multival_t *serviceSearchDescriptor;
282 } clientopts_t;
283
284 static clientopts_t *clientopts_new();
285 static void clientopts_free(clientopts_t *list);
286
287 extern ns_ldap_error_t *__ns_ldap_print_config(int);
288 extern void __ns_ldap_default_config();
289 extern int __ns_ldap_download(const char *, char *, char *, ns_ldap_error_t **);
290
291 /* Function prototypes (these could be static) */
292 static void usage(void);
293
294 static int credCheck(clientopts_t *arglist);
295 static int adminCredCheck(clientopts_t *arglist);
296 static int clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal);
297 static int parseParam(char *param, char **paramVal);
298 static void dumpargs(clientopts_t *arglist);
299 static int num_args(clientopts_t *arglist);
300
301 static int file_backup(void);
302 static int recover(int saveState);
303 static int mod_backup(void);
304 static int mod_recover(void);
305 static void mod_cleanup(void);
306
307 static int client_list(clientopts_t *arglist);
308 static int client_manual(clientopts_t *arglist);
309 static int client_mod(clientopts_t *arglist);
310 static int client_uninit(clientopts_t *arglist);
311 static int client_genProfile(clientopts_t *arglist);
312 static int client_init(clientopts_t *arglist);
313 static int file_move(const char *from, const char *to);
314
315 static int start_services(int flag);
316 static int stop_services(int saveState);
317 static boolean_t is_service(const char *fmri, const char *state);
318 static int wait_till(const char *fmri, const char *state, useconds_t max,
319 const char *what, boolean_t check_maint);
320 static int do_service(const char *fmri, boolean_t waitflag, int dowhat,
321 const char *state);
322 static useconds_t get_timeout_value(int dowhat, const char *fmri,
323 useconds_t default_val);
324
325 int
main(int argc,char ** argv)326 main(int argc, char **argv)
327 {
328 char *ret_locale, *ret_textdomain;
329 int retcode;
330 int paramFlag;
331 char *attrVal;
332 int sysinfostatus;
333 clientopts_t *optlist = NULL;
334 int op_manual = 0, op_mod = 0, op_uninit = 0;
335 int op_list = 0, op_init = 0, op_genprofile = 0;
336 extern char *optarg;
337 extern int optind;
338 int option;
339
340 ret_locale = setlocale(LC_ALL, "");
341 if (ret_locale == NULL) {
342 CLIENT_FPUTS(gettext("Unable to set locale.\n"), stderr);
343 }
344 ret_textdomain = textdomain(TEXT_DOMAIN);
345 if (ret_textdomain == NULL) {
346 CLIENT_FPUTS(gettext("Unable to set textdomain.\n"), stderr);
347 }
348
349 openlog("ldapclient", LOG_PID, LOG_USER);
350
351 /* get name that invoked us */
352 if (cmd = strrchr(argv[0], '/'))
353 ++cmd;
354 else
355 cmd = argv[0];
356
357 sysinfostatus = sysinfo(SI_SRPC_DOMAIN, dname_buf, BUFSIZ);
358 if (0 < sysinfostatus)
359 dname = &dname_buf[0];
360
361 optlist = clientopts_new();
362 if (optlist == NULL) {
363 CLIENT_FPUTS(
364 gettext("Error getting optlist (malloc fail)\n"),
365 stderr);
366 exit(CLIENT_ERR_FAIL);
367 }
368
369 optind = 1;
370 while (optind < argc) {
371 option = getopt(argc, argv, "vqa:ID:w:j:y:z:");
372
373 switch (option) {
374 case 'v':
375 mode_verbose = 1;
376 break;
377 case 'q':
378 mode_quiet = 1;
379 break;
380 case 'a':
381 attrVal = NULL;
382 paramFlag = parseParam(optarg, &attrVal);
383 if (paramFlag == CLIENT_ERR_PARSE) {
384 CLIENT_FPRINTF(stderr,
385 gettext("Unrecognized "
386 "parameter \"%s\"\n"),
387 optarg);
388 usage();
389 exit(CLIENT_ERR_FAIL);
390 }
391 if (paramFlag == NS_LDAP_BINDPASSWD_P &&
392 optlist->proxyPassword != NULL) {
393 (void) fprintf(stderr,
394 gettext("The -a proxyPassword option is "
395 "mutually exclusive of -y. "
396 "-a proxyPassword is ignored.\n"));
397 break;
398 }
399 if (paramFlag == NS_LDAP_ADMIN_BINDPASSWD_P &&
400 optlist->adminPassword != NULL) {
401 (void) fprintf(stderr,
402 gettext("The -a adminPassword option is "
403 "mutually exclusive of -z. "
404 "-a adminPassword is ignored.\n"));
405 break;
406 }
407 retcode = clientSetParam(optlist, paramFlag, attrVal);
408 if (retcode != CLIENT_SUCCESS) {
409 CLIENT_FPRINTF(
410 stderr,
411 gettext("Error (%d) setting "
412 "param \"%s\"\n"),
413 retcode, optarg);
414 usage();
415 exit(CLIENT_ERR_FAIL);
416 }
417 break;
418 case 'D':
419 optlist->bindDN = strdup(optarg);
420 break;
421 case 'w':
422 if (optlist->bindPasswd != NULL) {
423 CLIENT_FPRINTF(stderr,
424 gettext("The -w option is mutually "
425 "exclusive of -j. -w is ignored."));
426 break;
427 }
428
429 if (optarg[0] == '-' && optarg[1] == '\0') {
430 /* Ask for a password later */
431 break;
432 }
433
434 optlist->bindPasswd = strdup(optarg);
435 break;
436 case 'j':
437 if (optlist->bindPasswd != NULL) {
438 (void) fprintf(stderr,
439 gettext("The -w option is mutually "
440 "exclusive of -j. -w is ignored.\n"));
441 free(optlist->bindPasswd);
442 }
443 optlist->bindPasswd = readPwd(optarg);
444 if (optlist->bindPasswd == NULL) {
445 exit(CLIENT_ERR_FAIL);
446 }
447 break;
448 case 'y':
449 if (optlist->proxyPassword != NULL) {
450 (void) fprintf(stderr,
451 gettext("The -a proxyPassword option is "
452 "mutually exclusive of -y. "
453 "-a proxyPassword is ignored.\n"));
454 }
455 optlist->proxyPassword = readPwd(optarg);
456 if (optlist->proxyPassword == NULL) {
457 exit(CLIENT_ERR_FAIL);
458 }
459 break;
460 case 'z':
461 if (optlist->adminPassword != NULL) {
462 (void) fprintf(stderr,
463 gettext("The -a adminPassword option is "
464 "mutually exclusive of -z. "
465 "-a adminPassword is ignored.\n"));
466 }
467 optlist->adminPassword = readPwd(optarg);
468 if (optlist->adminPassword == NULL) {
469 exit(CLIENT_ERR_FAIL);
470 }
471 break;
472 case EOF:
473 if (strcmp(argv[optind], "init") == 0) {
474 op_init = 1;
475 } else if (strcmp(argv[optind], "manual") == 0) {
476 op_manual = 1;
477 } else if (strcmp(argv[optind], "mod") == 0) {
478 op_mod = 1;
479 } else if (strcmp(argv[optind], "list") == 0) {
480 op_list = 1;
481 } else if (strcmp(argv[optind], "uninit") == 0) {
482 op_uninit = 1;
483 } else if (strcmp(argv[optind], "genprofile") == 0) {
484 gen = 1;
485 op_genprofile = 1;
486 } else if (optind == argc-1) {
487 retcode = clientSetParam(
488 optlist,
489 NS_LDAP_SERVERS_P,
490 argv[optind]); /* ipAddr */
491 if (retcode != CLIENT_SUCCESS) {
492 CLIENT_FPRINTF(
493 stderr,
494 gettext("Error (%d) setting "
495 "serverList param.\n"),
496 retcode);
497 usage();
498 exit(CLIENT_ERR_FAIL);
499 }
500 } else {
501 CLIENT_FPUTS(
502 gettext("Error parsing "
503 "command line\n"),
504 stderr);
505 usage();
506 exit(CLIENT_ERR_FAIL);
507 }
508 optind++; /* get past the verb and keep trying */
509 break;
510 /* Backwards compatibility to support system install */
511 case 'I':
512 sysid_install = B_TRUE;
513 op_init = 1;
514 mode_quiet = 1;
515 break;
516 case '?':
517 usage();
518 CLIENT_FPUTS(gettext("\nOr\n\n"), stderr);
519 gen = 1;
520 usage();
521 exit(CLIENT_ERR_FAIL);
522 break;
523 }
524
525 }
526
527 if ((getuid() != 0) && (!op_genprofile)) {
528 (void) puts(
529 "You must be root (SuperUser) to run this command.");
530 usage();
531 exit(CLIENT_ERR_FAIL);
532 }
533
534 /*
535 * All command line arguments are finished being parsed now
536 */
537
538 /* *** Do semantic checking here *** */
539
540 /* if gen and no no searchBase then err */
541 if (gen && !optlist->defaultSearchBase) {
542 CLIENT_FPUTS(
543 gettext("ldapclient: Missing required attrName "
544 "defaultSearchBase\n"),
545 stderr);
546 usage();
547 clientopts_free(optlist);
548 exit(CLIENT_ERR_FAIL);
549 }
550
551 /*
552 * if init or manual, and if adminDN is specified then enableShadowUpdate
553 * must be set to TRUE.
554 */
555 if ((op_init || op_manual) &&
556 (!optlist->enableShadowUpdate ||
557 strcasecmp(optlist->enableShadowUpdate, "TRUE") != 0) &&
558 (optlist->adminDN || optlist->adminPassword)) {
559 CLIENT_FPUTS(
560 gettext("ldapclient: adminDN and adminPassword must not "
561 "be specified if enableShadowUpdate is not set to TRUE \n"),
562 stderr);
563 usage();
564 clientopts_free(optlist);
565 exit(CLIENT_ERR_FAIL);
566 }
567
568 /* Only one verb can be specified */
569 if ((op_init + op_manual + op_mod + op_uninit +
570 op_list + op_genprofile) != 1) {
571 usage();
572 clientopts_free(optlist);
573 exit(CLIENT_ERR_FAIL);
574 }
575
576 /* *** We passed semantic checking, so now do the operation *** */
577
578 if (mode_verbose) {
579 CLIENT_FPUTS(gettext("Arguments parsed:\n"), stderr);
580 dumpargs(optlist);
581 }
582
583
584 /* handle "ldapclient list" here. err checking done in func */
585 if (op_list) {
586 if (mode_verbose)
587 CLIENT_FPUTS(
588 gettext("Handling list option\n"),
589 stderr);
590 retcode = client_list(optlist);
591 }
592
593 /* handle "ldapclient uninit" here */
594 if (op_uninit) {
595 if (mode_verbose)
596 CLIENT_FPUTS(
597 gettext("Handling uninit option\n"),
598 stderr);
599 retcode = client_uninit(optlist);
600 }
601
602 /* handle "ldapclient init" (profile) */
603 if (op_init) {
604 if (mode_verbose)
605 CLIENT_FPUTS(
606 gettext("Handling init option\n"),
607 stderr);
608 retcode = client_init(optlist);
609 }
610
611 /* handle "genprofile" here */
612 if (op_genprofile) {
613 if (mode_verbose)
614 CLIENT_FPUTS(
615 gettext("Handling genProfile\n"),
616 stderr);
617 retcode = client_genProfile(optlist);
618 }
619
620 /* handle "ldapclient manual" here */
621 if (op_manual) {
622 if (mode_verbose)
623 CLIENT_FPUTS(
624 gettext("Handling manual option\n"),
625 stderr);
626 retcode = client_manual(optlist);
627 }
628
629 /* handle "ldapclient mod" here */
630 if (op_mod) {
631 if (mode_verbose)
632 CLIENT_FPUTS(
633 gettext("Handling mod option\n"),
634 stderr);
635 retcode = client_mod(optlist);
636 }
637
638 clientopts_free(optlist);
639 if ((retcode == CLIENT_SUCCESS) ||
640 (retcode == CLIENT_ERR_FAIL) ||
641 (retcode == CLIENT_ERR_CREDENTIAL))
642 return (retcode);
643 else
644 return (CLIENT_ERR_FAIL);
645 }
646
647 static int
client_list(clientopts_t * arglist)648 client_list(clientopts_t *arglist)
649 {
650 ns_ldap_error_t *errorp;
651 int retcode = CLIENT_SUCCESS;
652
653 if (num_args(arglist) > 0) {
654 CLIENT_FPUTS(
655 gettext("No args supported with \"list\" option\n"),
656 stderr);
657 usage();
658 return (CLIENT_ERR_FAIL); /* exit code here ? */
659 }
660 if ((errorp = __ns_ldap_print_config(mode_verbose)) != NULL) {
661 retcode = CLIENT_ERR_FAIL;
662 CLIENT_FPUTS(
663 gettext("Cannot get print configuration\n"),
664 stderr);
665 CLIENT_FPUTS(errorp->message, stderr);
666 (void) __ns_ldap_freeError(&errorp);
667 CLIENT_FPUTC('\n', stderr);
668 }
669
670 return (retcode);
671 }
672
673 static int
client_uninit(clientopts_t * arglist)674 client_uninit(clientopts_t *arglist)
675 {
676 int retcode = CLIENT_SUCCESS;
677 ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
678
679 if (mode_verbose) {
680 CLIENT_FPUTS(
681 gettext("Restoring machine to previous "
682 "configuration state\n"),
683 stderr);
684 }
685
686 if (num_args(arglist) > 0) {
687 CLIENT_FPUTS(
688 gettext("No args supported with \"uninit\" option\n"),
689 stderr);
690 usage();
691 return (CLIENT_ERR_FAIL);
692 }
693
694 (void) __ns_ldap_self_gssapi_config(&config);
695
696 retcode = stop_services(STATE_SAVE);
697
698 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE)
699 (void) system("/usr/sbin/cryptoadm enable metaslot");
700
701 if (retcode != CLIENT_SUCCESS) {
702 CLIENT_FPUTS(
703 gettext("Errors stopping network services.\n"), stderr);
704 /* restart whatever services we can */
705 (void) start_services(START_RESET);
706 return (CLIENT_ERR_FAIL);
707 }
708
709 retcode = recover(STATE_SAVE);
710 if (retcode != CLIENT_SUCCESS) {
711 CLIENT_FPUTS(
712 gettext("Cannot recover the configuration on "
713 "this machine.\n"),
714 stderr);
715 (void) start_services(START_RESET);
716 } else {
717 retcode = start_services(START_UNINIT);
718 if (retcode != CLIENT_SUCCESS) {
719 CLIENT_FPUTS(
720 gettext("Config restored but problems "
721 "encountered resetting network "
722 "services.\n"),
723 stderr);
724 }
725 }
726
727 if (retcode == CLIENT_SUCCESS) {
728 CLIENT_FPUTS(
729 gettext("System successfully recovered\n"),
730 stderr);
731 }
732
733 return (retcode);
734 }
735
736 /*
737 * The following macro is used to do a __ns_ldap_setParam().
738 * On every call, the return code is checked, and if there was
739 * a problem then the error message is printed, the ldaperr
740 * is freed and we return from the function with the offending
741 * error return code. This macro keeps us from having to
742 * repeat this code for every call to setParam as was done
743 * in the previous incarnation of ldapclient.
744 *
745 * assumes a "retcode" variable is available for status
746 */
747 #define LDAP_SET_PARAM(argval, argdef) \
748 retcode = 0; \
749 if (NULL != argval) { \
750 ns_ldap_error_t *ldaperr; \
751 retcode = __ns_ldap_setParam(argdef, (void *)argval, &ldaperr); \
752 if (retcode != NS_LDAP_SUCCESS) { \
753 if (NULL != ldaperr) { \
754 CLIENT_FPUTS(ldaperr->message, stderr); \
755 CLIENT_FPUTC('\n', stderr); \
756 (void) __ns_ldap_freeError(&ldaperr); \
757 } \
758 return (retcode ? CLIENT_ERR_FAIL : CLIENT_SUCCESS); \
759 } \
760 }
761
762 /*
763 * The following macro is used to check if an arg has already been set
764 * and issues an error message, a usage message and then returns an error.
765 * This was made into a macro to avoid the duplication of this code many
766 * times in the function below.
767 */
768 #define LDAP_CHECK_INVALID(arg, param) \
769 if (arg) { \
770 CLIENT_FPRINTF(stderr, gettext("Invalid parameter (%s) " \
771 "specified\n"), param); \
772 usage(); \
773 return (CLIENT_ERR_FAIL); \
774 }
775
776 static int
client_manual(clientopts_t * arglist)777 client_manual(clientopts_t *arglist)
778 {
779 int counter;
780 int domain_fp;
781 ns_ldap_error_t *errorp;
782 int ret_copy;
783 int reset_ret;
784 int retcode = CLIENT_SUCCESS;
785
786 if (dname == NULL) {
787 CLIENT_FPUTS(
788 gettext("Manual failed: System domain not set and "
789 "no domainName specified.\n"),
790 stderr);
791 return (CLIENT_ERR_FAIL);
792 }
793
794 if (arglist->defaultSearchBase == NULL) {
795 CLIENT_FPUTS(
796 gettext("Manual failed: Missing required "
797 "defaultSearchBase attribute.\n"),
798 stderr);
799 return (CLIENT_ERR_FAIL);
800 }
801
802 if ((arglist->defaultServerList == NULL) &&
803 (arglist->preferredServerList == NULL)) {
804 CLIENT_FPUTS(
805 gettext("Manual failed: Missing required "
806 "defaultServerList or preferredServerList "
807 "attribute.\n"),
808 stderr);
809 return (CLIENT_ERR_FAIL);
810 }
811
812 if (arglist->profileTTL != NULL) {
813 CLIENT_FPUTS(
814 gettext("Manual aborted: profileTTL is not supported "
815 "in manual mode.\n"),
816 stderr);
817 return (CLIENT_ERR_FAIL);
818 }
819
820 if (arglist->profileName != NULL) {
821 CLIENT_FPUTS(
822 gettext("Manual aborted: profileName is not supported "
823 "in manual mode.\n"),
824 stderr);
825 return (CLIENT_ERR_FAIL);
826 }
827
828 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
829 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
830
831 __ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */
832 __ns_ldap_default_config();
833
834 /* Set version to latest (not version 1) */
835 LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
836
837 /* Set profileTTL to 0 since NO profile on manual */
838 LDAP_SET_PARAM(CACHETTL_OFF, NS_LDAP_CACHETTL_P);
839
840 /* Set additional valid params from command line */
841 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
842 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
843 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
844 LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
845 LDAP_SET_PARAM(arglist->enableShadowUpdate,
846 NS_LDAP_ENABLE_SHADOW_UPDATE_P);
847 LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P);
848 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
849 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
850 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
851 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
852 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
853 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
854 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
855 LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P);
856 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
857 LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
858
859 for (counter = 0;
860 counter < arglist->serviceAuthenticationMethod->count;
861 counter++) {
862
863 LDAP_SET_PARAM(
864 arglist->serviceAuthenticationMethod->optlist[counter],
865 NS_LDAP_SERVICE_AUTH_METHOD_P);
866 }
867 for (counter = 0;
868 counter < arglist->serviceCredentialLevel->count;
869 counter++) {
870
871 LDAP_SET_PARAM(
872 arglist->serviceCredentialLevel->optlist[counter],
873 NS_LDAP_SERVICE_CRED_LEVEL_P);
874 }
875 for (counter = 0;
876 counter < arglist->objectclassMap->count;
877 counter++) {
878
879 LDAP_SET_PARAM(arglist->objectclassMap->optlist[counter],
880 NS_LDAP_OBJECTCLASSMAP_P);
881 }
882 for (counter = 0; counter < arglist->attributeMap->count; counter++) {
883 LDAP_SET_PARAM(arglist->attributeMap->optlist[counter],
884 NS_LDAP_ATTRIBUTEMAP_P);
885 }
886 for (counter = 0;
887 counter < arglist->serviceSearchDescriptor->count;
888 counter++) {
889
890 LDAP_SET_PARAM(
891 arglist->serviceSearchDescriptor->optlist[counter],
892 NS_LDAP_SERVICE_SEARCH_DESC_P);
893 }
894
895 retcode = credCheck(arglist);
896 if (retcode == CLIENT_SUCCESS)
897 retcode = adminCredCheck(arglist);
898 if (retcode != CLIENT_SUCCESS) {
899 CLIENT_FPUTS(
900 gettext("Error in setting up credentials\n"),
901 stderr);
902 return (retcode);
903 }
904
905 if (mode_verbose)
906 CLIENT_FPUTS(
907 gettext("About to modify this machines "
908 "configuration by writing the files\n"),
909 stderr);
910
911 /* get ready to start playing with files */
912 retcode = stop_services(STATE_SAVE);
913 if (retcode != CLIENT_SUCCESS) {
914 CLIENT_FPUTS(
915 gettext("Errors stopping network services.\n"), stderr);
916 return (CLIENT_ERR_FAIL);
917 }
918
919 /* Save orig versions of files */
920 retcode = file_backup();
921 if (retcode == CLIENT_ERR_RESTORE) {
922 CLIENT_FPUTS(
923 gettext("System not in state to enable ldap client.\n"),
924 stderr);
925
926 reset_ret = start_services(START_RESET);
927 if (reset_ret != CLIENT_SUCCESS) {
928 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
929 "starting services during reset\n"),
930 reset_ret);
931 }
932 return (retcode);
933 } else if (retcode != CLIENT_SUCCESS) {
934 CLIENT_FPUTS(
935 gettext("Save of system configuration failed! "
936 "Attempting recovery.\n"),
937 stderr);
938 retcode = recover(STATE_NOSAVE);
939 if (retcode != CLIENT_SUCCESS) {
940 CLIENT_FPUTS(
941 gettext("Recovery of systems configuration "
942 "failed. Manual intervention of "
943 "config files is required.\n"),
944 stderr);
945 return (retcode);
946 }
947
948 reset_ret = start_services(START_RESET);
949 if (reset_ret != CLIENT_SUCCESS) {
950 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
951 "starting services during reset\n"),
952 reset_ret);
953 }
954
955 return (retcode);
956 }
957
958 /* Dump new files */
959 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
960 if (errorp != NULL) {
961 CLIENT_FPRINTF(stderr,
962 gettext("%s manual: errorp is not NULL; %s\n"),
963 cmd, errorp->message);
964 retcode = recover(STATE_NOSAVE);
965 if (retcode != CLIENT_SUCCESS) {
966 CLIENT_FPUTS(
967 gettext("Recovery of systems configuration "
968 "failed. Manual intervention of "
969 "config files is required.\n"),
970 stderr);
971 return (retcode);
972 }
973 reset_ret = start_services(START_RESET);
974 if (reset_ret != CLIENT_SUCCESS) {
975 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
976 "starting services during reset\n"),
977 reset_ret);
978 }
979 (void) __ns_ldap_freeError(&errorp);
980 return (CLIENT_ERR_FAIL);
981 }
982
983 /* if (credargs(arglist)) */
984 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
985 if (errorp != NULL) {
986 CLIENT_FPRINTF(stderr,
987 gettext("%s init: errorp is not NULL; %s\n"),
988 cmd, errorp->message);
989 retcode = recover(STATE_NOSAVE);
990 if (retcode != CLIENT_SUCCESS) {
991 CLIENT_FPUTS(
992 gettext("Recovery of systems configuration "
993 "failed. Manual intervention of "
994 "config files is required.\n"),
995 stderr);
996 return (retcode);
997 }
998 reset_ret = start_services(START_RESET);
999 if (reset_ret != CLIENT_SUCCESS) {
1000 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1001 "starting services during reset\n"),
1002 reset_ret);
1003 }
1004 (void) __ns_ldap_freeError(&errorp);
1005 return (CLIENT_ERR_FAIL);
1006 }
1007
1008 ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
1009 if (ret_copy != 0) {
1010 CLIENT_FPRINTF(stderr,
1011 gettext("Error %d copying (%s) -> (%s)\n"),
1012 ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
1013 retcode = recover(STATE_NOSAVE);
1014 if (retcode != CLIENT_SUCCESS) {
1015 CLIENT_FPUTS(
1016 gettext("Recovery of systems configuration "
1017 "failed. Manual intervention of "
1018 "config files is required.\n"),
1019 stderr);
1020 }
1021 reset_ret = start_services(START_RESET);
1022 if (reset_ret != CLIENT_SUCCESS) {
1023 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1024 "starting services during reset\n"),
1025 reset_ret);
1026 }
1027 return (CLIENT_ERR_FAIL);
1028 }
1029
1030 if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
1031 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
1032 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
1033 retcode = recover(STATE_NOSAVE);
1034 if (retcode != CLIENT_SUCCESS) {
1035 CLIENT_FPUTS(
1036 gettext("Recovery of systems configuration "
1037 "failed. Manual intervention of "
1038 "config files is required.\n"),
1039 stderr);
1040 return (CLIENT_ERR_FAIL);
1041 }
1042 reset_ret = start_services(START_RESET);
1043 if (reset_ret != CLIENT_SUCCESS) {
1044 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1045 "starting services during reset\n"),
1046 reset_ret);
1047 }
1048 return (CLIENT_ERR_FAIL);
1049 }
1050 (void) write(domain_fp, dname, strlen(dname));
1051 (void) write(domain_fp, "\n", 1);
1052 (void) close(domain_fp);
1053
1054 retcode = start_services(START_INIT);
1055
1056 if (retcode == CLIENT_SUCCESS) {
1057 CLIENT_FPUTS(gettext("System successfully configured\n"),
1058 stderr);
1059 } else {
1060 CLIENT_FPUTS(gettext("Error resetting system.\n"
1061 "Recovering old system settings.\n"), stderr),
1062
1063 /* stop any started services for recover */
1064 /* don't stomp on history of saved services state */
1065 reset_ret = stop_services(STATE_NOSAVE);
1066 if (reset_ret != CLIENT_SUCCESS) {
1067 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1068 "stopping services during reset\n"),
1069 reset_ret);
1070 /* Coninue and try to recover what we can */
1071 }
1072 reset_ret = recover(STATE_NOSAVE);
1073 if (reset_ret != CLIENT_SUCCESS) {
1074 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1075 "recovering service files during "
1076 "reset\n"), reset_ret);
1077 /* Continue and start what we can */
1078 }
1079 reset_ret = start_services(START_RESET);
1080 if (reset_ret != CLIENT_SUCCESS) {
1081 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1082 "starting services during reset\n"),
1083 reset_ret);
1084 }
1085 }
1086
1087 return (retcode);
1088 }
1089
1090 static int
client_mod(clientopts_t * arglist)1091 client_mod(clientopts_t *arglist)
1092 {
1093 int counter;
1094 int domain_fp;
1095 ns_ldap_error_t *errorp;
1096 int reset_ret;
1097 int retcode = CLIENT_SUCCESS;
1098
1099 __ns_ldap_setServer(TRUE); /* Need this for _ns_setParam() */
1100 if ((errorp = __ns_ldap_LoadConfiguration()) != NULL) {
1101 CLIENT_FPUTS(gettext("Cannot get load configuration\n"),
1102 stderr);
1103 CLIENT_FPUTS(errorp->message, stderr);
1104 CLIENT_FPUTC('\n', stderr);
1105 (void) __ns_ldap_freeError(&errorp);
1106 return (CLIENT_ERR_FAIL);
1107 }
1108
1109 if (arglist->profileTTL != NULL) {
1110 CLIENT_FPUTS(
1111 gettext("Mod aborted: profileTTL modification is "
1112 "not allowed in mod mode.\n"),
1113 stderr);
1114 return (CLIENT_ERR_FAIL);
1115 }
1116
1117 if (arglist->profileName != NULL) {
1118 CLIENT_FPUTS(
1119 gettext("Mod aborted: profileName modification is "
1120 "not allowed. If you want to use profiles "
1121 "generate one with genProfile and load it "
1122 "on the server with ldapadd.\n"),
1123 stderr);
1124 return (CLIENT_ERR_FAIL);
1125 }
1126
1127 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
1128 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
1129
1130 /* Set additional valid params from command line */
1131 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
1132 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
1133 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
1134 LDAP_SET_PARAM(arglist->proxyDN, NS_LDAP_BINDDN_P);
1135 LDAP_SET_PARAM(arglist->adminDN, NS_LDAP_ADMIN_BINDDN_P);
1136 LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
1137 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
1138 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
1139 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
1140 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
1141 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
1142 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
1143 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
1144 LDAP_SET_PARAM(arglist->adminPassword, NS_LDAP_ADMIN_BINDPASSWD_P);
1145 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1146 LDAP_SET_PARAM(arglist->enableShadowUpdate,
1147 NS_LDAP_ENABLE_SHADOW_UPDATE_P);
1148 LDAP_SET_PARAM(arglist->certificatePath, NS_LDAP_HOST_CERTPATH_P);
1149
1150 for (counter = 0;
1151 counter < arglist->serviceAuthenticationMethod->count;
1152 counter++) {
1153
1154 LDAP_SET_PARAM(
1155 arglist->serviceAuthenticationMethod->optlist[counter],
1156 NS_LDAP_SERVICE_AUTH_METHOD_P);
1157 }
1158 for (counter = 0;
1159 counter < arglist->serviceCredentialLevel->count;
1160 counter++) {
1161
1162 LDAP_SET_PARAM(
1163 arglist->serviceCredentialLevel->optlist[counter],
1164 NS_LDAP_SERVICE_CRED_LEVEL_P);
1165 }
1166 for (counter = 0;
1167 counter < arglist->objectclassMap->count;
1168 counter++) {
1169
1170 LDAP_SET_PARAM(
1171 arglist->objectclassMap->optlist[counter],
1172 NS_LDAP_OBJECTCLASSMAP_P);
1173 }
1174 for (counter = 0;
1175 counter < arglist->attributeMap->count;
1176 counter++) {
1177
1178 LDAP_SET_PARAM(
1179 arglist->attributeMap->optlist[counter],
1180 NS_LDAP_ATTRIBUTEMAP_P);
1181 }
1182 for (counter = 0;
1183 counter < arglist->serviceSearchDescriptor->count;
1184 counter++) {
1185
1186 LDAP_SET_PARAM(
1187 arglist->serviceSearchDescriptor->optlist[counter],
1188 NS_LDAP_SERVICE_SEARCH_DESC_P);
1189 }
1190
1191 retcode = credCheck(arglist);
1192 if (retcode == CLIENT_SUCCESS)
1193 retcode = adminCredCheck(arglist);
1194 if (retcode != CLIENT_SUCCESS) {
1195 CLIENT_FPUTS(
1196 gettext("Error in setting up credentials\n"),
1197 stderr);
1198 return (retcode);
1199 }
1200
1201 if (mode_verbose)
1202 CLIENT_FPUTS(
1203 gettext("About to modify this machines configuration "
1204 "by writing the files\n"),
1205 stderr);
1206
1207 /* get ready to start playing with files */
1208 retcode = stop_services(STATE_SAVE);
1209 if (retcode != CLIENT_SUCCESS) {
1210 CLIENT_FPUTS(
1211 gettext("Errors stopping network services.\n"), stderr);
1212 return (CLIENT_ERR_FAIL);
1213 }
1214
1215 /* Temporarily save orig versions of files */
1216 retcode = mod_backup();
1217 if (retcode != CLIENT_SUCCESS) {
1218 CLIENT_FPUTS(
1219 gettext("Unable to backup the ldap client files!\n"),
1220 stderr);
1221
1222 return (retcode);
1223
1224 }
1225
1226 /* Dump new files */
1227 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
1228 if (errorp != NULL) {
1229 CLIENT_FPRINTF(stderr,
1230 gettext("%s mod: errorp is not NULL; %s\n"),
1231 cmd, errorp->message);
1232 retcode = mod_recover();
1233 if (retcode != CLIENT_SUCCESS) {
1234 CLIENT_FPUTS(
1235 gettext("Recovery of systems configuration "
1236 "failed. Manual intervention of "
1237 "config files is required.\n"),
1238 stderr);
1239 }
1240 (void) __ns_ldap_freeError(&errorp);
1241 reset_ret = start_services(START_RESET);
1242 if (reset_ret != CLIENT_SUCCESS) {
1243 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1244 "starting services during reset\n"),
1245 reset_ret);
1246 }
1247 return (CLIENT_ERR_FAIL);
1248 }
1249
1250 /* if (credargs(arglist)) */
1251 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
1252 if (errorp != NULL) {
1253 CLIENT_FPRINTF(stderr,
1254 gettext("%s mod: errorp is not NULL; %s\n"),
1255 cmd, errorp->message);
1256 retcode = mod_recover();
1257 if (retcode != CLIENT_SUCCESS) {
1258 CLIENT_FPUTS(
1259 gettext("Recovery of systems configuration "
1260 "failed. Manual intervention of "
1261 "config files is required.\n"),
1262 stderr);
1263 }
1264 (void) __ns_ldap_freeError(&errorp);
1265 reset_ret = start_services(START_RESET);
1266 if (reset_ret != CLIENT_SUCCESS) {
1267 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1268 "starting services during reset\n"),
1269 reset_ret);
1270 }
1271 return (CLIENT_ERR_FAIL);
1272 }
1273
1274 if ((domain_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
1275 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
1276 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
1277 retcode = mod_recover();
1278 if (retcode != CLIENT_SUCCESS) {
1279 CLIENT_FPUTS(
1280 gettext("Recovery of systems configuration "
1281 "failed! Machine needs to be "
1282 "fixed!\n"),
1283 stderr);
1284 }
1285 reset_ret = start_services(START_RESET);
1286 if (reset_ret != CLIENT_SUCCESS) {
1287 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1288 "starting services during reset\n"),
1289 reset_ret);
1290 }
1291 return (CLIENT_ERR_FAIL);
1292 }
1293 (void) write(domain_fp, dname, strlen(dname));
1294 (void) write(domain_fp, "\n", 1);
1295 (void) close(domain_fp);
1296
1297 retcode = start_services(START_INIT);
1298
1299 if (retcode == CLIENT_SUCCESS) {
1300 CLIENT_FPUTS(gettext("System successfully configured\n"),
1301 stderr);
1302 } else {
1303 CLIENT_FPUTS(gettext("Error resetting system.\n"
1304 "Recovering old system settings.\n"), stderr),
1305
1306 /* stop any started services for recover */
1307 /* don't stomp on history of saved services state */
1308 reset_ret = stop_services(STATE_NOSAVE);
1309 if (reset_ret != CLIENT_SUCCESS) {
1310 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1311 "stopping services during reset\n"),
1312 reset_ret);
1313 /* Coninue and try to recover what we can */
1314 }
1315 reset_ret = mod_recover();
1316 if (reset_ret != CLIENT_SUCCESS) {
1317 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1318 "recovering service files during "
1319 "reset\n"), reset_ret);
1320 /* Continue and start what we can */
1321 }
1322 reset_ret = start_services(START_RESET);
1323 if (reset_ret != CLIENT_SUCCESS) {
1324 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1325 "starting services during reset\n"),
1326 reset_ret);
1327 }
1328 }
1329
1330 /* Cleanup temporary files created by mod_backup() */
1331 mod_cleanup();
1332
1333 return (retcode);
1334 }
1335
1336
1337 static int
client_genProfile(clientopts_t * arglist)1338 client_genProfile(clientopts_t *arglist)
1339 {
1340 int counter;
1341 int retcode; /* required for LDAP_SET_PARAM macro */
1342 ns_ldap_error_t *errorp;
1343
1344 if (mode_verbose)
1345 CLIENT_FPUTS(gettext("About to generate a profile\n"), stderr);
1346
1347 /* *** Check for invalid args *** */
1348 LDAP_CHECK_INVALID(arglist->proxyDN, "proxyDN");
1349 LDAP_CHECK_INVALID(arglist->proxyPassword, "proxyPassword");
1350 LDAP_CHECK_INVALID(arglist->enableShadowUpdate,
1351 "enableShadowUpdate");
1352 LDAP_CHECK_INVALID(arglist->adminDN, "adminDN");
1353 LDAP_CHECK_INVALID(arglist->adminPassword, "adminPassword");
1354 LDAP_CHECK_INVALID(arglist->certificatePath, "certificatePath");
1355 LDAP_CHECK_INVALID(arglist->domainName, "domainName");
1356 LDAP_CHECK_INVALID(arglist->bindDN, "bind DN");
1357 LDAP_CHECK_INVALID(arglist->bindPasswd, "bind password");
1358 /* *** End check for invalid args *** */
1359
1360 if (arglist->profileName == NULL) {
1361 if (mode_verbose)
1362 CLIENT_FPUTS(
1363 gettext("No profile specified. "
1364 "Using \"default\"\n"),
1365 stderr);
1366 arglist->profileName = "default";
1367 }
1368
1369 __ns_ldap_setServer(TRUE);
1370 __ns_ldap_default_config();
1371
1372 /* Set version to latest (not version 1) */
1373 LDAP_SET_PARAM(NS_LDAP_VERSION, NS_LDAP_FILE_VERSION_P);
1374
1375 /* Set additional valid params from command line */
1376 LDAP_SET_PARAM(arglist->authenticationMethod, NS_LDAP_AUTH_P);
1377 LDAP_SET_PARAM(arglist->defaultSearchBase, NS_LDAP_SEARCH_BASEDN_P);
1378 LDAP_SET_PARAM(arglist->credentialLevel, NS_LDAP_CREDENTIAL_LEVEL_P);
1379 LDAP_SET_PARAM(arglist->profileTTL, NS_LDAP_CACHETTL_P);
1380 LDAP_SET_PARAM(arglist->searchTimeLimit, NS_LDAP_SEARCH_TIME_P);
1381 LDAP_SET_PARAM(arglist->preferredServerList, NS_LDAP_SERVER_PREF_P);
1382 LDAP_SET_PARAM(arglist->profileName, NS_LDAP_PROFILE_P);
1383 LDAP_SET_PARAM(arglist->followReferrals, NS_LDAP_SEARCH_REF_P);
1384 LDAP_SET_PARAM(arglist->defaultSearchScope, NS_LDAP_SEARCH_SCOPE_P);
1385 LDAP_SET_PARAM(arglist->bindTimeLimit, NS_LDAP_BIND_TIME_P);
1386 LDAP_SET_PARAM(arglist->defaultServerList, NS_LDAP_SERVERS_P);
1387
1388 for (counter = 0;
1389 counter < arglist->serviceAuthenticationMethod->count;
1390 counter++) {
1391
1392 LDAP_SET_PARAM(
1393 arglist->serviceAuthenticationMethod->optlist[counter],
1394 NS_LDAP_SERVICE_AUTH_METHOD_P);
1395 }
1396 for (counter = 0;
1397 counter < arglist->serviceCredentialLevel->count;
1398 counter++) {
1399
1400 LDAP_SET_PARAM(
1401 arglist->serviceCredentialLevel->optlist[counter],
1402 NS_LDAP_SERVICE_CRED_LEVEL_P);
1403 }
1404 for (counter = 0;
1405 counter < arglist->objectclassMap->count;
1406 counter++) {
1407
1408 LDAP_SET_PARAM(
1409 arglist->objectclassMap->optlist[counter],
1410 NS_LDAP_OBJECTCLASSMAP_P);
1411 }
1412 for (counter = 0;
1413 counter < arglist->attributeMap->count;
1414 counter++) {
1415
1416 LDAP_SET_PARAM(
1417 arglist->attributeMap->optlist[counter],
1418 NS_LDAP_ATTRIBUTEMAP_P);
1419 }
1420 for (counter = 0;
1421 counter < arglist->serviceSearchDescriptor->count;
1422 counter++) {
1423
1424 LDAP_SET_PARAM(
1425 arglist->serviceSearchDescriptor->optlist[counter],
1426 NS_LDAP_SERVICE_SEARCH_DESC_P);
1427 }
1428
1429 errorp = __ns_ldap_DumpLdif(NULL);
1430 if (errorp != NULL) {
1431 CLIENT_FPUTS(errorp->message, stderr);
1432 CLIENT_FPUTC('\n', stderr);
1433 (void) __ns_ldap_freeError(&errorp);
1434 return (CLIENT_ERR_FAIL);
1435 }
1436
1437 return (CLIENT_SUCCESS);
1438 }
1439
1440 /* INET6_ADDRSTRLEN + ":" + <5-digit port> + some round-up */
1441 #define MAX_HOSTADDR_LEN (INET6_ADDRSTRLEN + 6 + 12)
1442
1443 static int
client_init(clientopts_t * arglist)1444 client_init(clientopts_t *arglist)
1445 {
1446 int profile_fp;
1447 int retcode = CLIENT_SUCCESS;
1448 ns_ldap_error_t *errorp;
1449 int reset_ret;
1450 int ret_copy;
1451 ns_standalone_conf_t cfg = standaloneDefaults;
1452 ns_auth_t auth = {NS_LDAP_AUTH_NONE,
1453 NS_LDAP_TLS_NONE,
1454 NS_LDAP_SASL_NONE,
1455 NS_LDAP_SASLOPT_NONE};
1456 char peer[MAX_HOSTADDR_LEN];
1457 ns_auth_t **authMethod;
1458 int **credLevel, i;
1459 char *cred;
1460
1461 if (mode_verbose)
1462 CLIENT_FPUTS(
1463 gettext("About to configure machine by downloading "
1464 "a profile\n"),
1465 stderr);
1466
1467 if (dname == NULL) {
1468 CLIENT_FPUTS(
1469 gettext("Init failed: System domain not set and "
1470 "no domainName specified.\n"),
1471 stderr);
1472 return (CLIENT_ERR_FAIL);
1473 }
1474
1475 if (!arglist->defaultServerList) {
1476 CLIENT_FPUTS(gettext("Missing LDAP server address\n"), stderr);
1477 return (CLIENT_ERR_FAIL);
1478 }
1479
1480 /* *** Check for invalid args *** */
1481 LDAP_CHECK_INVALID(arglist->defaultSearchBase,
1482 "defaultSearchBase");
1483 LDAP_CHECK_INVALID(arglist->profileTTL,
1484 "profileTTL");
1485 LDAP_CHECK_INVALID(arglist->searchTimeLimit,
1486 "searchTimeLimit");
1487 LDAP_CHECK_INVALID(arglist->preferredServerList,
1488 "preferredServerList");
1489 LDAP_CHECK_INVALID(arglist->followReferrals,
1490 "followReferrals");
1491 LDAP_CHECK_INVALID(arglist->defaultSearchScope,
1492 "defaultSearchScope");
1493 LDAP_CHECK_INVALID(arglist->bindTimeLimit,
1494 "bindTimeLimit");
1495
1496 LDAP_CHECK_INVALID(arglist->objectclassMap->count,
1497 "objectclassMap");
1498 LDAP_CHECK_INVALID(arglist->attributeMap->count,
1499 "attributeMap");
1500 LDAP_CHECK_INVALID(arglist->serviceAuthenticationMethod->count,
1501 "serviceAuthenticationMethod");
1502 LDAP_CHECK_INVALID(arglist->serviceCredentialLevel->count,
1503 "serviceCredentialLevel");
1504 LDAP_CHECK_INVALID(arglist->serviceSearchDescriptor->count,
1505 "serviceSearchDescriptor");
1506 /* *** End check for invalid args *** */
1507
1508 if (arglist->profileName == NULL) {
1509 if (mode_verbose)
1510 CLIENT_FPUTS(
1511 gettext("No profile specified. "
1512 "Using \"default\"\n"),
1513 stderr);
1514 arglist->profileName = "default";
1515 }
1516
1517 (void) strncpy(peer, arglist->defaultServerList, MAX_HOSTADDR_LEN - 1);
1518 if (separatePort(peer, &cfg.SA_SERVER, &cfg.SA_PORT) > 0) {
1519 return (CLIENT_ERR_FAIL);
1520 }
1521
1522 if (arglist->bindDN != NULL) {
1523 cfg.SA_CRED = "proxy";
1524 /*
1525 * We don't want to force users to always specify authentication
1526 * method when we can infer it. If users want SSL, he/she would
1527 * have to specify appropriate -a though.
1528 */
1529 auth.type = NS_LDAP_AUTH_SIMPLE;
1530 if (arglist->bindPasswd == NULL) {
1531 arglist->bindPasswd =
1532 getpassphrase("Bind Password:");
1533 if (arglist->bindPasswd == NULL) {
1534 CLIENT_FPUTS(gettext("Get password failed\n"),
1535 stderr);
1536
1537 if (gStartLdap == START_RESET)
1538 (void) start_service(LDAP_FMRI, B_TRUE);
1539
1540 return (CLIENT_ERR_CREDENTIAL);
1541 }
1542 }
1543 }
1544 cfg.SA_BIND_DN = arglist->bindDN;
1545 cfg.SA_BIND_PWD = arglist->bindPasswd;
1546
1547 if (arglist->authenticationMethod != NULL) {
1548 if (__ns_ldap_initAuth(arglist->authenticationMethod,
1549 &auth, &errorp) != NS_LDAP_SUCCESS) {
1550 if (errorp != NULL) {
1551 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1552 (void) __ns_ldap_freeError(&errorp);
1553 }
1554
1555 if (gStartLdap == START_RESET)
1556 (void) start_service(LDAP_FMRI, B_TRUE);
1557
1558 return (CLIENT_ERR_FAIL);
1559 }
1560 cfg.SA_AUTH = &auth;
1561 }
1562 cfg.SA_CRED = arglist->credentialLevel;
1563
1564 cfg.SA_DOMAIN = arglist->domainName;
1565 cfg.SA_PROFILE_NAME = arglist->profileName;
1566 cfg.SA_CERT_PATH = arglist->certificatePath;
1567
1568 cfg.type = NS_LDAP_SERVER;
1569
1570 if (__ns_ldap_initStandalone(&cfg, &errorp) != NS_LDAP_SUCCESS) {
1571 if (errorp != NULL) {
1572 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1573 (void) __ns_ldap_freeError(&errorp);
1574 }
1575
1576 if (gStartLdap == START_RESET)
1577 (void) start_service(LDAP_FMRI, B_TRUE);
1578
1579 return (CLIENT_ERR_FAIL);
1580 }
1581
1582 if (arglist->proxyDN != NULL && arglist->proxyPassword == NULL) {
1583 arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
1584 if (arglist->proxyPassword == NULL) {
1585 CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
1586
1587 if (gStartLdap == START_RESET)
1588 (void) start_service(LDAP_FMRI, B_TRUE);
1589
1590 return (CLIENT_ERR_CREDENTIAL);
1591 }
1592 }
1593 if (arglist->proxyDN != NULL && arglist->proxyPassword != NULL) {
1594 if (__ns_ldap_setParam(NS_LDAP_BINDDN_P,
1595 arglist->proxyDN, &errorp) != NS_LDAP_SUCCESS) {
1596 if (errorp != NULL) {
1597 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1598 (void) __ns_ldap_freeError(&errorp);
1599 }
1600 return (CLIENT_ERR_CREDENTIAL);
1601 }
1602 if (__ns_ldap_setParam(NS_LDAP_BINDPASSWD_P,
1603 arglist->proxyPassword, &errorp) != NS_LDAP_SUCCESS) {
1604 if (errorp != NULL) {
1605 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1606 (void) __ns_ldap_freeError(&errorp);
1607 }
1608 return (CLIENT_ERR_CREDENTIAL);
1609 }
1610 }
1611
1612 if (arglist->enableShadowUpdate != NULL) {
1613 LDAP_SET_PARAM(arglist->enableShadowUpdate,
1614 NS_LDAP_ENABLE_SHADOW_UPDATE_P);
1615 }
1616
1617 if (arglist->enableShadowUpdate &&
1618 strcasecmp(arglist->enableShadowUpdate, "TRUE") == 0 &&
1619 arglist->adminDN != NULL && arglist->adminPassword == NULL) {
1620 arglist->adminPassword = getpassphrase("admin Bind Password:");
1621 if (arglist->adminPassword == NULL) {
1622 CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
1623
1624 if (gStartLdap == START_RESET)
1625 (void) start_service(LDAP_FMRI, B_TRUE);
1626
1627 return (CLIENT_ERR_CREDENTIAL);
1628 }
1629 }
1630 if (arglist->adminDN != NULL && arglist->adminPassword != NULL) {
1631 if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDDN_P,
1632 arglist->adminDN, &errorp) != NS_LDAP_SUCCESS) {
1633 if (errorp != NULL) {
1634 CLIENT_FPRINTF(stderr, "%s\n", errorp->message);
1635 (void) __ns_ldap_freeError(&errorp);
1636 }
1637 return (CLIENT_ERR_CREDENTIAL);
1638 }
1639 if (__ns_ldap_setParam(NS_LDAP_ADMIN_BINDPASSWD_P,
1640 arglist->adminPassword, &errorp) != NS_LDAP_SUCCESS) {
1641 if (errorp != NULL) {
1642 CLIENT_FPRINTF(stderr, "%s\n", errorp->message);
1643 (void) __ns_ldap_freeError(&errorp);
1644 }
1645 return (CLIENT_ERR_CREDENTIAL);
1646 }
1647 }
1648
1649 if (arglist->authenticationMethod != NULL) {
1650 if (__ns_ldap_getParam(NS_LDAP_AUTH_P,
1651 (void ***)&authMethod, &errorp) != NS_LDAP_SUCCESS) {
1652 if (errorp != NULL) {
1653 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1654 (void) __ns_ldap_freeError(&errorp);
1655 }
1656 return (CLIENT_ERR_CREDENTIAL);
1657 }
1658
1659 if (authMethod != NULL) {
1660 for (i = 0; authMethod[i] != NULL; ++i) {
1661 if (authMethod[i]->type == auth.type) {
1662 break;
1663 }
1664 }
1665
1666 if (authMethod[i] == NULL) {
1667 CLIENT_FPRINTF(stderr, gettext(
1668 "Warning: init authentication method "
1669 "not found in DUAConfigProfile.\n"));
1670 } else {
1671 if (i != 0) {
1672 CLIENT_FPRINTF(stderr,
1673 gettext(
1674 "Warning: init authentication"
1675 "method using secondary "
1676 "authentication method from "
1677 "DUAConfigProfile.\n"));
1678 }
1679 }
1680 (void) __ns_ldap_freeParam((void ***) &authMethod);
1681 }
1682 }
1683
1684 if (arglist->credentialLevel != NULL) {
1685 if (__ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
1686 (void ***)&credLevel, &errorp) != NS_LDAP_SUCCESS) {
1687 if (errorp != NULL) {
1688 CLIENT_FPRINTF(stderr, "%s", errorp->message);
1689 (void) __ns_ldap_freeError(&errorp);
1690 }
1691 return (CLIENT_ERR_CREDENTIAL);
1692 }
1693 if (credLevel != NULL) {
1694 for (i = 0; credLevel[i] != NULL; ++i) {
1695 switch (*credLevel[i]) {
1696 case NS_LDAP_CRED_ANON :
1697 cred = "none";
1698 break;
1699 case NS_LDAP_CRED_PROXY :
1700 cred = "proxy";
1701 break;
1702 case NS_LDAP_CRED_SELF :
1703 cred = "self";
1704 break;
1705 default:
1706 continue;
1707 }
1708 if (strcmp(cred,
1709 arglist->credentialLevel) == 0) {
1710 break;
1711 }
1712 }
1713 if (credLevel[i] == NULL) {
1714 CLIENT_FPRINTF(stderr, gettext(
1715 "Warning: init credential level not found "
1716 "in DUAConfigProfile.\n"));
1717 } else {
1718 if (i != 0) {
1719 CLIENT_FPRINTF(stderr,
1720 gettext("Warning: "
1721 "init credential level using "
1722 "secondary credential level from "
1723 "DUAConfigProfile.\n"));
1724 }
1725 }
1726 (void) __ns_ldap_freeParam((void ***) &credLevel);
1727 }
1728 }
1729
1730 retcode = credCheck(arglist);
1731 if (retcode == CLIENT_SUCCESS)
1732 retcode = adminCredCheck(arglist);
1733 if (retcode != CLIENT_SUCCESS) {
1734 CLIENT_FPUTS(
1735 gettext("Error in setting up credentials\n"), stderr);
1736
1737 if (gStartLdap == START_RESET)
1738 (void) start_service(LDAP_FMRI, B_TRUE);
1739
1740 return (retcode);
1741 }
1742
1743 if (mode_verbose)
1744 CLIENT_FPUTS(
1745 gettext("About to modify this machines configuration "
1746 "by writing the files\n"),
1747 stderr);
1748
1749 /* get ready to start playing with files */
1750 retcode = stop_services(STATE_SAVE);
1751 if (retcode != CLIENT_SUCCESS) {
1752 CLIENT_FPUTS(
1753 gettext("Errors stopping network services.\n"), stderr);
1754
1755 if (gStartLdap == START_RESET)
1756 (void) start_service(LDAP_FMRI, B_TRUE);
1757
1758 return (CLIENT_ERR_FAIL);
1759 }
1760
1761 /* Save orig versions of files */
1762 retcode = file_backup();
1763 if (retcode == CLIENT_ERR_RESTORE) {
1764 CLIENT_FPUTS(
1765 gettext("System not in state to enable ldap client.\n"),
1766 stderr);
1767
1768 return (retcode);
1769
1770 } else if (retcode != CLIENT_SUCCESS) {
1771 CLIENT_FPUTS(
1772 gettext("Save of system configuration failed. "
1773 "Attempting recovery.\n"),
1774 stderr);
1775 retcode = recover(STATE_NOSAVE);
1776 if (retcode != CLIENT_SUCCESS) {
1777 CLIENT_FPUTS(
1778 gettext("Recovery of systems configuration "
1779 "failed. Manual intervention of "
1780 "config files is required.\n"),
1781 stderr);
1782 }
1783
1784 reset_ret = start_services(START_RESET);
1785 if (reset_ret != CLIENT_SUCCESS) {
1786 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1787 "starting services during reset\n"),
1788 reset_ret);
1789 }
1790
1791 return (retcode);
1792 }
1793
1794 /* Dump new files */
1795 errorp = __ns_ldap_DumpConfiguration(NSCONFIGFILE);
1796 if (NULL != errorp) {
1797 CLIENT_FPRINTF(stderr,
1798 gettext("%s init: errorp is not NULL; %s\n"),
1799 cmd, errorp->message);
1800 retcode = recover(STATE_NOSAVE);
1801 if (retcode != CLIENT_SUCCESS) {
1802 CLIENT_FPUTS(
1803 gettext("Recovery of systems configuration "
1804 "failed. Manual intervention of "
1805 "config files is required.\n"),
1806 stderr);
1807 return (CLIENT_ERR_FAIL);
1808 }
1809 (void) __ns_ldap_freeError(&errorp);
1810 reset_ret = start_services(START_RESET);
1811 if (reset_ret != CLIENT_SUCCESS) {
1812 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1813 "starting services during reset\n"),
1814 reset_ret);
1815 }
1816 return (CLIENT_ERR_FAIL);
1817 }
1818
1819 /* if (credargs(arglist)) */
1820 errorp = __ns_ldap_DumpConfiguration(NSCREDFILE);
1821 if (NULL != errorp) {
1822 CLIENT_FPRINTF(stderr,
1823 gettext("%s init: errorp is not NULL; %s\n"),
1824 cmd, errorp->message);
1825 retcode = recover(STATE_NOSAVE);
1826 if (retcode != CLIENT_SUCCESS) {
1827 CLIENT_FPUTS(
1828 gettext("Recovery of systems configuration "
1829 "failed. Manual intervention of "
1830 "config files is required.\n"),
1831 stderr);
1832 return (CLIENT_ERR_FAIL);
1833 }
1834 (void) __ns_ldap_freeError(&errorp);
1835 reset_ret = start_services(START_RESET);
1836 if (reset_ret != CLIENT_SUCCESS) {
1837 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1838 "starting services during reset\n"),
1839 reset_ret);
1840 }
1841 return (CLIENT_ERR_FAIL);
1842 }
1843
1844 ret_copy = system(CMD_CP " " NSSWITCH_LDAP " " NSSWITCH_CONF);
1845 if (ret_copy != 0) {
1846 CLIENT_FPRINTF(stderr,
1847 gettext("Error %d copying (%s) -> (%s)\n"),
1848 ret_copy, NSSWITCH_LDAP, NSSWITCH_CONF);
1849 retcode = recover(STATE_NOSAVE);
1850 if (retcode != CLIENT_SUCCESS) {
1851 CLIENT_FPUTS(
1852 gettext("Recovery of systems configuration "
1853 "failed. Manual intervention of "
1854 "config files is required.\n"),
1855 stderr);
1856 }
1857 reset_ret = start_services(START_RESET);
1858 if (reset_ret != CLIENT_SUCCESS) {
1859 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1860 "starting services during reset\n"),
1861 reset_ret);
1862 }
1863 return (CLIENT_ERR_FAIL);
1864 }
1865
1866 if ((profile_fp = open(DOMAINNAME, O_WRONLY|O_CREAT|O_TRUNC,
1867 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) { /* 0644 */
1868 CLIENT_FPRINTF(stderr, gettext("Cannot open %s\n"), DOMAINNAME);
1869 retcode = recover(STATE_NOSAVE);
1870 if (retcode != CLIENT_SUCCESS) {
1871 CLIENT_FPUTS(
1872 gettext("Recovery of systems configuration "
1873 "failed. Manual intervention of "
1874 "config files is required.\n"),
1875 stderr);
1876 return (CLIENT_ERR_FAIL);
1877 }
1878 reset_ret = start_services(START_RESET);
1879 if (reset_ret != CLIENT_SUCCESS) {
1880 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1881 "starting services during reset\n"),
1882 reset_ret);
1883 }
1884 return (CLIENT_ERR_FAIL);
1885 }
1886 (void) write(profile_fp, dname, strlen(dname));
1887 (void) write(profile_fp, "\n", 1);
1888 (void) close(profile_fp);
1889
1890 retcode = start_services(START_INIT);
1891
1892 if (retcode == CLIENT_SUCCESS) {
1893 CLIENT_FPUTS(gettext("System successfully configured\n"),
1894 stderr);
1895 } else {
1896 CLIENT_FPUTS(gettext("Error resetting system.\n"
1897 "Recovering old system settings.\n"), stderr),
1898
1899 /* stop any started services for recover */
1900 /* don't stomp on history of saved services state */
1901 reset_ret = stop_services(STATE_NOSAVE);
1902 if (reset_ret != CLIENT_SUCCESS) {
1903 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1904 "stopping services during reset\n"),
1905 reset_ret);
1906 /* Coninue and try to recover what we can */
1907 }
1908 reset_ret = recover(STATE_NOSAVE);
1909 if (reset_ret != CLIENT_SUCCESS) {
1910 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1911 "recovering service files during "
1912 "reset\n"), reset_ret);
1913 /* Continue and start what we can */
1914 }
1915 reset_ret = start_services(START_RESET);
1916 if (reset_ret != CLIENT_SUCCESS) {
1917 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
1918 "starting services during reset\n"),
1919 reset_ret);
1920 }
1921 }
1922
1923 return (retcode);
1924 }
1925
1926
1927 static void
usage(void)1928 usage(void)
1929 {
1930 if (mode_quiet)
1931 return;
1932
1933 if (gen == 0) {
1934 CLIENT_FPRINTF(stderr,
1935 gettext("Usage: %s [-v | -q] init | manual | mod | "
1936 "list | uninit [<args>]\n"),
1937 cmd);
1938
1939 CLIENT_FPRINTF(stderr,
1940 gettext("\n %s [-v | -q] [-a authenticationMethod]"
1941 " [-D bindDN]\n\t[-w bindPassword] [-j passswdFile]"
1942 " [-y proxyPasswordFile]\n\t"
1943 "[-z adminPasswordFile] init [<args>]\n"),
1944 cmd);
1945
1946 CLIENT_FPUTS(
1947 gettext("\nSet up a server or workstation as a "
1948 "client of an LDAP namespace.\n"),
1949 stderr);
1950 } else { /* genprofile */
1951 CLIENT_FPRINTF(stderr,
1952 gettext("Usage: %s [-v | -q] genprofile "
1953 "-a profileName=<name> "
1954 "-a defaultSearchBase=<base> <args>\n"),
1955 cmd);
1956
1957 CLIENT_FPUTS(
1958 gettext("\nGenerate a profile used to set up clients "
1959 "of an LDAP namespace.\n"),
1960 stderr);
1961 }
1962 CLIENT_FPUTS(
1963 gettext("<args> take the form of \'-a attrName=attrVal\' as "
1964 "described in the\n"),
1965 stderr);
1966 CLIENT_FPUTS(gettext("man page: ldapclient(1M)\n"), stderr);
1967 }
1968
1969
1970 /*
1971 * stop_services is called to stop network services prior to their
1972 * config files being moved/changed. In case a later recovery is needed
1973 * (an error occurs during config), we detect whether the service is
1974 * running and store that info so that a reset will only start services
1975 * that were stopped here.
1976 *
1977 * In terms of SMF, this translates to disabling the services. So we
1978 * try to disable them if they are in any other state
1979 *
1980 * Stop order :
1981 * sendmail, nscd, autofs, ldap.client, nisd (rpc), inetinit(domainname)
1982 */
1983 static int
stop_services(int saveState)1984 stop_services(int saveState)
1985 {
1986 int ret;
1987
1988 if (mode_verbose) {
1989 CLIENT_FPUTS(gettext("Stopping network services\n"), stderr);
1990 }
1991
1992 if (!is_service(SENDMAIL_FMRI, SCF_STATE_STRING_DISABLED)) {
1993 if (mode_verbose)
1994 CLIENT_FPUTS(gettext("Stopping sendmail\n"), stderr);
1995 ret = disable_service(SENDMAIL_FMRI, B_TRUE);
1996 if (ret != CLIENT_SUCCESS) {
1997 /* Not serious, but tell user what to do */
1998 CLIENT_FPRINTF(stderr, gettext("Stopping sendmail "
1999 "failed with (%d). You may need to restart "
2000 "it manually for changes to take effect.\n"),
2001 ret);
2002 } else enableFlag |= SENDMAIL_ON;
2003 } else {
2004 if (mode_verbose)
2005 CLIENT_FPUTS(gettext("sendmail not running\n"), stderr);
2006 }
2007
2008 if (!is_service(NSCD_FMRI, SCF_STATE_STRING_DISABLED)) {
2009 if (mode_verbose)
2010 CLIENT_FPUTS(gettext("Stopping nscd\n"), stderr);
2011 ret = disable_service(NSCD_FMRI, B_TRUE);
2012 if (ret != CLIENT_SUCCESS) {
2013 CLIENT_FPRINTF(stderr, gettext("Stopping nscd "
2014 "failed with (%d)\n"), ret);
2015 return (CLIENT_ERR_FAIL);
2016 } else enableFlag |= NSCD_ON;
2017 } else {
2018 if (mode_verbose)
2019 CLIENT_FPUTS(gettext("nscd not running\n"), stderr);
2020 }
2021
2022 if (!is_service(AUTOFS_FMRI, SCF_STATE_STRING_DISABLED)) {
2023 if (mode_verbose)
2024 CLIENT_FPUTS(gettext("Stopping autofs\n"), stderr);
2025 ret = disable_service(AUTOFS_FMRI, B_TRUE);
2026 if (ret != CLIENT_SUCCESS) {
2027 /* Not serious, but tell user what to do */
2028 CLIENT_FPRINTF(stderr, gettext("Stopping autofs "
2029 "failed with (%d). You may need to restart "
2030 "it manually for changes to take effect.\n"),
2031 ret);
2032 } else enableFlag |= AUTOFS_ON;
2033 } else {
2034 if (mode_verbose)
2035 CLIENT_FPUTS(gettext("autofs not running\n"), stderr);
2036 }
2037
2038 if (!is_service(LDAP_FMRI, SCF_STATE_STRING_DISABLED)) {
2039 if (saveState)
2040 gStartLdap = START_RESET;
2041 if (mode_verbose)
2042 CLIENT_FPUTS(gettext("Stopping ldap\n"), stderr);
2043 ret = disable_service(LDAP_FMRI, B_TRUE);
2044 if (ret != CLIENT_SUCCESS) {
2045 CLIENT_FPRINTF(stderr, gettext("Stopping ldap "
2046 "failed with (%d)\n"), ret);
2047 return (CLIENT_ERR_FAIL);
2048 }
2049 } else {
2050 if (mode_verbose)
2051 CLIENT_FPUTS(gettext("ldap not running\n"),
2052 stderr);
2053 }
2054
2055 if (!is_service(YP_FMRI, SCF_STATE_STRING_DISABLED)) {
2056 if (saveState)
2057 gStartYp = START_RESET;
2058 if (mode_verbose)
2059 CLIENT_FPUTS(gettext("Stopping nis(yp)\n"), stderr);
2060 ret = disable_service(YP_FMRI, B_TRUE);
2061 if (ret != 0) {
2062 CLIENT_FPRINTF(stderr, gettext("Stopping nis(yp) "
2063 "failed with (%d)\n"), ret);
2064 return (CLIENT_ERR_FAIL);
2065 }
2066 } else {
2067 if (mode_verbose)
2068 CLIENT_FPUTS(gettext("nis(yp) not running\n"),
2069 stderr);
2070 }
2071
2072 return (CLIENT_SUCCESS);
2073 }
2074
2075 /*
2076 * start_services is called to start up network services after config
2077 * files have all been setup or recovered. In the case of an error, the
2078 * files will be recovered and start_services will be called with the
2079 * "reset" flag set so that only those services that were earlier stopped
2080 * will be started. If it is not a reset, then the services associated
2081 * with files "recovered" will attempt to be started.
2082 */
2083 static int
start_services(int flag)2084 start_services(int flag)
2085 {
2086 int sysret, retcode = CLIENT_SUCCESS, rc = NS_LDAP_SUCCESS;
2087 FILE *domain_fp;
2088 char domainname[BUFSIZ];
2089 char cmd_domain_start[BUFSIZ];
2090 int domainlen;
2091 ns_ldap_self_gssapi_config_t config = NS_LDAP_SELF_GSSAPI_CONFIG_NONE;
2092 ns_ldap_error_t *errorp = NULL;
2093
2094 if (mode_verbose) {
2095 CLIENT_FPUTS(gettext("Starting network services\n"), stderr);
2096 }
2097
2098 /* Read in current defaultdomain so we can set it */
2099 domain_fp = fopen(DOMAINNAME, "r");
2100 if (domain_fp == NULL) {
2101 CLIENT_FPRINTF(stderr, gettext("Error opening defaultdomain "
2102 "(%d)\n"), errno);
2103 /* if we did an ldap init, we must have domain */
2104 if (flag == START_INIT)
2105 return (CLIENT_ERR_FAIL);
2106 } else {
2107 if (fgets(domainname, BUFSIZ, domain_fp) == NULL) {
2108 CLIENT_FPUTS(gettext("Error reading defaultdomain\n"),
2109 stderr);
2110 return (CLIENT_ERR_FAIL);
2111 }
2112
2113 if (fclose(domain_fp) != 0) {
2114 CLIENT_FPRINTF(stderr,
2115 gettext("Error closing defaultdomain (%d)\n"),
2116 errno);
2117 return (CLIENT_ERR_FAIL);
2118 }
2119 domainlen = strlen(domainname);
2120 /* sanity check to make sure sprintf will fit */
2121 if (domainlen > (BUFSIZE - sizeof (CMD_DOMAIN_START) -
2122 sizeof (TO_DEV_NULL) - 3)) {
2123 CLIENT_FPUTS(gettext("Specified domainname is "
2124 "too large\n"), stderr);
2125 return (CLIENT_ERR_FAIL);
2126 }
2127 if (domainname[domainlen-1] == '\n')
2128 domainname[domainlen-1] = 0;
2129 /* buffer size is checked above */
2130 (void) snprintf(cmd_domain_start, BUFSIZ, "%s %s %s",
2131 CMD_DOMAIN_START, domainname, TO_DEV_NULL);
2132 }
2133
2134 /*
2135 * We can be starting services after an init in which case
2136 * we want to start ldap and not start yp.
2137 */
2138 if (flag == START_INIT) {
2139 sysret = system(cmd_domain_start);
2140 if (mode_verbose)
2141 CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
2142 CMD_DOMAIN_START, domainname,
2143 (sysret == 0) ? gettext("success") :
2144 gettext("failed"));
2145 if (sysret != 0) {
2146 CLIENT_FPRINTF(stderr, gettext("\"%s\" returned: %d\n"),
2147 CMD_DOMAIN_START, sysret);
2148
2149 retcode = CLIENT_ERR_FAIL;
2150 }
2151
2152 if ((rc = __ns_ldap_self_gssapi_config(&config)) !=
2153 NS_LDAP_SUCCESS) {
2154 CLIENT_FPRINTF(stderr, gettext("Error (%d) while "
2155 "checking sasl/GSSAPI configuration\n"),
2156 rc);
2157 retcode = CLIENT_ERR_FAIL;
2158 }
2159
2160 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE) {
2161
2162 rc = __ns_ldap_check_dns_preq(
2163 1, mode_verbose, mode_quiet,
2164 NSSWITCH_LDAP, config, &errorp);
2165 if (errorp)
2166 (void) __ns_ldap_freeError(&errorp);
2167
2168 if (rc != NS_LDAP_SUCCESS)
2169 retcode = CLIENT_ERR_FAIL;
2170 }
2171
2172 if (rc == NS_LDAP_SUCCESS &&
2173 start_service(LDAP_FMRI, B_TRUE) != CLIENT_SUCCESS)
2174 retcode = CLIENT_ERR_FAIL;
2175
2176 if (config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
2177 rc == NS_LDAP_SUCCESS && retcode == CLIENT_SUCCESS) {
2178 rc = __ns_ldap_check_gssapi_preq(
2179 1, mode_verbose, mode_quiet, config,
2180 &errorp);
2181 if (errorp)
2182 (void) __ns_ldap_freeError(&errorp);
2183
2184 if (rc != NS_LDAP_SUCCESS)
2185 retcode = CLIENT_ERR_FAIL;
2186
2187 }
2188 /* No YP after init */
2189 /*
2190 * Or we can be starting services after an uninit or error
2191 * recovery. We want to start whatever services were running
2192 * before. In the case of error recovery, it is the services
2193 * that were running before we stopped them (flags set in
2194 * stop_services). If it is an uninit then we determine
2195 * which services to start based on the files we recovered
2196 * (flags set in recover).
2197 */
2198 } else {
2199 /* uninit and recover should set flags of what to start */
2200 if (domain_fp) {
2201 sysret = system(cmd_domain_start);
2202 if (mode_verbose)
2203 CLIENT_FPRINTF(stderr, "start: %s %s... %s\n",
2204 CMD_DOMAIN_START, domainname,
2205 (sysret == 0) ? gettext("success") :
2206 gettext("failed"));
2207 if (sysret != 0) {
2208 CLIENT_FPRINTF(stderr, gettext("\"%s\" "
2209 "returned: %d\n"),
2210 CMD_DOMAIN_START, sysret);
2211
2212 retcode = CLIENT_ERR_FAIL;
2213 }
2214 }
2215
2216 if (gStartLdap == flag) {
2217 if (!(is_service(LDAP_FMRI, SCF_STATE_STRING_ONLINE)))
2218 if (start_service(LDAP_FMRI, B_TRUE)
2219 != CLIENT_SUCCESS)
2220 retcode = CLIENT_ERR_FAIL;
2221 }
2222
2223 if (gStartYp == flag) {
2224 if (!(is_service(YP_FMRI, SCF_STATE_STRING_ONLINE)))
2225 (void) start_service(YP_FMRI, B_TRUE);
2226 }
2227 }
2228 if ((enableFlag & AUTOFS_ON) &&
2229 !(is_service(AUTOFS_FMRI, SCF_STATE_STRING_ONLINE)))
2230 (void) start_service(AUTOFS_FMRI, B_TRUE);
2231
2232 if ((enableFlag & NSCD_ON) &&
2233 !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE)))
2234 (void) start_service(NSCD_FMRI, B_TRUE);
2235
2236 #if 0
2237 if (flag == START_INIT && config != NS_LDAP_SELF_GSSAPI_CONFIG_NONE &&
2238 retcode == CLIENT_SUCCESS &&
2239 !(is_service(NSCD_FMRI, SCF_STATE_STRING_ONLINE))) {
2240 CLIENT_FPRINTF(stderr, "start: %s\n",
2241 gettext("self/sasl/GSSAPI is configured"
2242 " but nscd is not online"));
2243 retcode = CLIENT_ERR_FAIL;
2244 }
2245 #endif
2246
2247 if ((enableFlag & SENDMAIL_ON) &&
2248 !(is_service(SENDMAIL_FMRI, SCF_STATE_STRING_ONLINE)))
2249 (void) start_service(SENDMAIL_FMRI, B_TRUE);
2250
2251 /*
2252 * Restart name-service milestone so that any consumer
2253 * which depends on it will be restarted.
2254 */
2255 (void) restart_service(NS_MILESTONE_FMRI, B_TRUE);
2256 return (retcode);
2257 }
2258
2259 /*
2260 * credCheck is called to check if credentials are required for this
2261 * configuration. Currently, this means that if any credentialLevel is
2262 * proxy and any authenticationMethod is something other than none, then
2263 * credential info is required (proxyDN and proxyPassword).
2264 */
2265 static int
credCheck(clientopts_t * arglist)2266 credCheck(clientopts_t *arglist)
2267 {
2268 int counter;
2269 int **credLevel;
2270 ns_auth_t **authMethod;
2271 char **proxyDN, **proxyPassword;
2272 ns_ldap_error_t *errorp;
2273 int credProxy, authNotNone;
2274 int retcode;
2275
2276 /* If credentialLevel is proxy, make sure we have proxyDN and proxyPassword */
2277 retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
2278 (void ***)&credLevel, &errorp);
2279 if (retcode != 0) {
2280 CLIENT_FPRINTF(stderr,
2281 gettext("Error %d while trying to retrieve "
2282 "credLevel\n"),
2283 retcode);
2284 return (CLIENT_ERR_FAIL);
2285 }
2286 retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
2287 (void ***)&authMethod, &errorp);
2288 if (retcode != 0) {
2289 CLIENT_FPRINTF(stderr,
2290 gettext("Error %d while trying to retrieve "
2291 "authMethod\n"), retcode);
2292 return (CLIENT_ERR_FAIL);
2293 }
2294 retcode = __ns_ldap_getParam(NS_LDAP_BINDDN_P,
2295 (void ***)&proxyDN, &errorp);
2296 if (retcode != 0) {
2297 CLIENT_FPRINTF(stderr,
2298 gettext("Error %d while trying to retrieve proxyDN\n"),
2299 retcode);
2300 return (CLIENT_ERR_FAIL);
2301 }
2302 retcode = __ns_ldap_getParam(NS_LDAP_BINDPASSWD_P,
2303 (void ***)&proxyPassword, &errorp);
2304 if (retcode != 0) {
2305 CLIENT_FPRINTF(stderr,
2306 gettext("Error %d while trying to retrieve "
2307 "proxyPassword\n"), retcode);
2308 return (CLIENT_ERR_FAIL);
2309 }
2310
2311 if (mode_verbose) {
2312 CLIENT_FPRINTF(stderr,
2313 gettext("Proxy DN: %s\n"),
2314 (proxyDN && proxyDN[0]) ? proxyDN[0] : "NULL");
2315 CLIENT_FPRINTF(stderr,
2316 gettext("Proxy password: %s\n"),
2317 (proxyPassword && proxyPassword[0]) ?
2318 proxyPassword[0] : "NULL");
2319 }
2320
2321 credProxy = 0; /* flag to indicate if we have a credLevel of proxy */
2322 for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
2323 if (mode_verbose)
2324 CLIENT_FPRINTF(stderr,
2325 gettext("Credential level: %d\n"),
2326 *credLevel[counter]);
2327 if (*credLevel[counter] == NS_LDAP_CRED_PROXY) {
2328 credProxy = 1;
2329 break;
2330 }
2331 }
2332
2333 authNotNone = 0; /* flag for authMethod other than none */
2334 for (counter = 0;
2335 authMethod && authMethod[counter] != NULL;
2336 counter++) {
2337
2338 if (mode_verbose)
2339 CLIENT_FPRINTF(stderr,
2340 gettext("Authentication method: %d\n"),
2341 authMethod[counter]->type);
2342 if (authMethod[counter]->type != NS_LDAP_AUTH_NONE &&
2343 !(authMethod[counter]->type == NS_LDAP_AUTH_TLS &&
2344 authMethod[counter]->tlstype == NS_LDAP_TLS_NONE)) {
2345 authNotNone = 1;
2346 break;
2347 }
2348 }
2349
2350 /* First, if we don't need proxyDN/Password then just return ok */
2351 if (!(credProxy && authNotNone)) {
2352 if (mode_verbose)
2353 CLIENT_FPUTS(
2354 gettext("No proxyDN/proxyPassword required\n"),
2355 stderr);
2356 return (CLIENT_SUCCESS);
2357 }
2358
2359 /* Now let's check if we have the cred stuff we need */
2360 if (!proxyDN || !proxyDN[0]) {
2361 CLIENT_FPUTS(
2362 gettext("credentialLevel is proxy and no proxyDN "
2363 "specified\n"),
2364 stderr);
2365 return (CLIENT_ERR_CREDENTIAL);
2366 }
2367
2368 /* If we need proxyPassword (prompt) */
2369 if (!proxyPassword || !proxyPassword[0]) {
2370 CLIENT_FPUTS(
2371 gettext("credentialLevel requires proxyPassword\n"),
2372 stderr);
2373 arglist->proxyPassword = getpassphrase("Proxy Bind Password:");
2374 if (arglist->proxyPassword == NULL) {
2375 CLIENT_FPUTS(gettext("Get password failed\n"), stderr);
2376 return (CLIENT_ERR_CREDENTIAL);
2377 }
2378 LDAP_SET_PARAM(arglist->proxyPassword, NS_LDAP_BINDPASSWD_P);
2379 if (retcode != 0) {
2380 CLIENT_FPUTS(
2381 gettext("setParam proxyPassword failed.\n"),
2382 stderr);
2383 return (CLIENT_ERR_CREDENTIAL);
2384 }
2385 }
2386
2387 return (CLIENT_SUCCESS);
2388 }
2389
2390 /*
2391 * adminCredCheck is called to check if the admin credential is required
2392 * for this configuration. This means that if enableShadowUpdate is set
2393 * to TRUE then credential info is required (adminDN and adminPassword).
2394 * One exception is that if there is a 'self' credentialLevel and
2395 * 'sasl/GSSAPI' authenticationMethod (i.e., possibly using Kerberos
2396 * host credential) then adminDN and adminPassword are not required.
2397 */
2398 static int
adminCredCheck(clientopts_t * arglist)2399 adminCredCheck(clientopts_t *arglist)
2400 {
2401 int counter;
2402 int **enabled = NULL;
2403 int **credLevel = NULL;
2404 char **adminDN = NULL;
2405 char **adminPassword = NULL;
2406 ns_auth_t **authMethod = NULL;
2407 ns_ldap_error_t *errorp = NULL;
2408 int credSelf, authSASLgss;
2409 int retcode, rc;
2410
2411 /* If shadow update not enabled, then no need to check */
2412 retcode = __ns_ldap_getParam(NS_LDAP_ENABLE_SHADOW_UPDATE_P,
2413 (void ***)&enabled, &errorp);
2414 if (retcode != 0) {
2415 CLIENT_FPRINTF(stderr,
2416 gettext("Error %d while trying to retrieve "
2417 "enableShadowUpdate\n"), retcode);
2418 rc = CLIENT_ERR_FAIL;
2419 goto out;
2420 }
2421 if (enabled == NULL ||
2422 *enabled[0] != NS_LDAP_ENABLE_SHADOW_UPDATE_TRUE) {
2423 if (mode_verbose)
2424 CLIENT_FPUTS(
2425 gettext("Shadow Update is not enabled, "
2426 "no adminDN/adminPassword is required.\n"), stderr);
2427 rc = CLIENT_SUCCESS;
2428 goto out;
2429 }
2430
2431 /* get credentialLevel */
2432 retcode = __ns_ldap_getParam(NS_LDAP_CREDENTIAL_LEVEL_P,
2433 (void ***)&credLevel, &errorp);
2434 if (retcode != 0) {
2435 CLIENT_FPRINTF(stderr,
2436 gettext("Error %d while trying to retrieve credLevel\n"),
2437 retcode);
2438 rc = CLIENT_ERR_FAIL;
2439 goto out;
2440 }
2441
2442 /* get AuthenticationMethod */
2443 retcode = __ns_ldap_getParam(NS_LDAP_AUTH_P,
2444 (void ***)&authMethod, &errorp);
2445 if (retcode != 0) {
2446 CLIENT_FPRINTF(stderr,
2447 gettext("Error %d while trying to retrieve authMethod\n"),
2448 retcode);
2449 rc = CLIENT_ERR_FAIL;
2450 goto out;
2451 }
2452
2453 /* get adminDN */
2454 retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDDN_P,
2455 (void ***)&adminDN, &errorp);
2456 if (retcode != 0) {
2457 CLIENT_FPRINTF(stderr,
2458 gettext("Error %d while trying to retrieve adminDN\n"),
2459 retcode);
2460 rc = CLIENT_ERR_FAIL;
2461 goto out;
2462 }
2463
2464 /* get adminPassword */
2465 retcode = __ns_ldap_getParam(NS_LDAP_ADMIN_BINDPASSWD_P,
2466 (void ***)&adminPassword, &errorp);
2467 if (retcode != 0) {
2468 CLIENT_FPRINTF(stderr,
2469 gettext("Error %d while trying to retrieve "
2470 "adminPassword\n"), retcode);
2471 rc = CLIENT_ERR_FAIL;
2472 goto out;
2473 }
2474
2475 if (mode_verbose) {
2476 CLIENT_FPRINTF(stderr,
2477 gettext("admin DN: %s\n"),
2478 (adminDN && adminDN[0]) ? adminDN[0] : "NULL");
2479 CLIENT_FPRINTF(stderr,
2480 gettext("admin password: %s\n"),
2481 (adminPassword && adminPassword[0]) ?
2482 adminPassword[0] : "NULL");
2483 }
2484
2485 credSelf = 0; /* flag to indicate if we have a credLevel of self */
2486 for (counter = 0; credLevel && credLevel[counter] != NULL; counter++) {
2487 if (mode_verbose)
2488 CLIENT_FPRINTF(stderr,
2489 gettext("Credential level: %d\n"),
2490 *credLevel[counter]);
2491 if (*credLevel[counter] == NS_LDAP_CRED_SELF) {
2492 credSelf = 1;
2493 break;
2494 }
2495 }
2496
2497 authSASLgss = 0; /* flag for authMethod of SASL/gssapi */
2498 for (counter = 0;
2499 authMethod && authMethod[counter] != NULL;
2500 counter++) {
2501
2502 if (mode_verbose)
2503 CLIENT_FPRINTF(stderr,
2504 gettext("Authentication sasl mechanism: %d\n"),
2505 authMethod[counter]->saslmech);
2506 if (authMethod[counter]->saslmech == NS_LDAP_SASL_GSSAPI) {
2507 authSASLgss = 1;
2508 break;
2509 }
2510 }
2511
2512 /* First, if we don't need adminDN/adminPassword then just return ok */
2513 if (credSelf && authSASLgss) {
2514 if (mode_verbose)
2515 CLIENT_FPUTS(
2516 gettext("A credential Level of self and an "
2517 "authentication method of sasl/GSSAPI is "
2518 "configured, no adminDN/adminPassword "
2519 "is required.\n"), stderr);
2520 rc = CLIENT_SUCCESS;
2521 goto out;
2522 }
2523
2524 /* Now let's check if we have the cred stuff we need */
2525 if (adminDN == NULL || adminDN[0] == '\0') {
2526 CLIENT_FPUTS(
2527 gettext("Shadow Update is enabled, but "
2528 "no adminDN is configured.\n"), stderr);
2529 rc = CLIENT_ERR_CREDENTIAL;
2530 goto out;
2531 }
2532
2533 /* If we need adminPassword (prompt) */
2534 if (adminPassword == NULL || adminPassword[0] == '\0') {
2535 CLIENT_FPUTS(
2536 gettext("Shadow Update requires adminPassword\n"),
2537 stderr);
2538 arglist->adminPassword = getpassphrase("admin Password:");
2539 if (arglist->adminPassword == NULL) {
2540 CLIENT_FPUTS(gettext("Unable to get admin password\n"),
2541 stderr);
2542 rc = CLIENT_ERR_CREDENTIAL;
2543 goto out;
2544 }
2545 LDAP_SET_PARAM(arglist->adminPassword,
2546 NS_LDAP_ADMIN_BINDPASSWD_P);
2547 if (retcode != 0) {
2548 CLIENT_FPUTS(
2549 gettext("setParam adminPassword failed.\n"),
2550 stderr);
2551 rc = CLIENT_ERR_CREDENTIAL;
2552 goto out;
2553 }
2554 }
2555
2556 rc = CLIENT_SUCCESS;
2557
2558 out:
2559 if (enabled != NULL)
2560 (void) __ns_ldap_freeParam((void ***)&enabled);
2561 if (credLevel != NULL)
2562 (void) __ns_ldap_freeParam((void ***)&credLevel);
2563 if (authMethod != NULL)
2564 (void) __ns_ldap_freeParam((void ***)&authMethod);
2565 if (adminDN != NULL)
2566 (void) __ns_ldap_freeParam((void ***)&adminDN);
2567 if (adminPassword != NULL)
2568 (void) __ns_ldap_freeParam((void ***)&adminPassword);
2569
2570 return (rc);
2571 }
2572
2573 /*
2574 * try to restore the previous name space on this machine
2575 */
2576 static int
recover(int saveState)2577 recover(int saveState)
2578 {
2579 struct stat buf;
2580 int stat_ret, retcode, fd;
2581 int domain = 0, domainlen;
2582 char yp_dir[BUFSIZE], yp_dir_back[BUFSIZE];
2583 char name[BUFSIZ];
2584 char *ldap_conf_file, *ldap_cred_file;
2585 char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
2586
2587 /* If running as Sysid Install become a no-op */
2588 if (sysid_install == B_TRUE)
2589 return (CLIENT_SUCCESS);
2590
2591 stat_ret = stat(LDAP_RESTORE_DIR, &buf);
2592 if (stat_ret != 0) {
2593 CLIENT_FPUTS(
2594 gettext("Cannot recover. No backup files "
2595 "found.\n"),
2596 stderr);
2597 CLIENT_FPUTS(
2598 gettext("\t Either this machine was not initialized\n"),
2599 stderr);
2600 CLIENT_FPUTS(
2601 gettext("\t by ldapclient or the backup files "
2602 "have been\n"),
2603 stderr);
2604 CLIENT_FPUTS(
2605 gettext("\t removed manually or with an \"uninit\"\n"),
2606 stderr);
2607 return (CLIENT_ERR_RESTORE); /* invalid backup */
2608 }
2609
2610 /*
2611 * Get domainname. Allow no domainname for the case where "files"
2612 * config was backed up.
2613 */
2614 stat_ret = stat(DOMAINNAME_BACK, &buf);
2615 if (mode_verbose)
2616 CLIENT_FPRINTF(stderr,
2617 gettext("recover: stat(%s)=%d\n"),
2618 DOMAINNAME_BACK, stat_ret);
2619 if (stat_ret == 0) {
2620 if (mode_verbose)
2621 CLIENT_FPRINTF(stderr,
2622 gettext("recover: open(%s)\n"),
2623 DOMAINNAME_BACK);
2624 fd = open(DOMAINNAME_BACK, O_RDONLY);
2625 if (mode_verbose)
2626 CLIENT_FPRINTF(stderr,
2627 gettext("recover: read(%s)\n"),
2628 DOMAINNAME_BACK);
2629 domainlen = read(fd, &(name[0]), BUFSIZ-1);
2630 (void) close(fd);
2631 if (domainlen < 0) {
2632 CLIENT_FPUTS(
2633 gettext("Cannot recover. Cannot determine "
2634 "previous domain name.\n"),
2635 stderr);
2636 return (CLIENT_ERR_RESTORE); /* invalid backup */
2637 } else {
2638 char *ptr;
2639
2640 ptr = strchr(&(name[0]), '\n');
2641 if (ptr != NULL)
2642 *ptr = '\0';
2643 else
2644 name[domainlen] = '\0';
2645
2646 if (mode_verbose)
2647 CLIENT_FPRINTF(stderr,
2648 gettext("recover: old domainname "
2649 "\"%s\"\n"), name);
2650
2651 if (strlen(name) == 0)
2652 domain = 0;
2653 else
2654 domain = 1; /* flag that we have domain */
2655
2656 }
2657 }
2658
2659
2660 /*
2661 * we can recover at this point
2662 * remove LDAP config files before restore
2663 */
2664 (void) unlink(NSCONFIGFILE);
2665 (void) unlink(NSCREDFILE);
2666
2667 ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
2668 ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
2669
2670 (void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2671 (void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
2672
2673 stat_ret = stat(ldap_file_back, &buf);
2674 if (mode_verbose)
2675 CLIENT_FPRINTF(stderr,
2676 gettext("recover: stat(%s)=%d\n"),
2677 ldap_file_back, stat_ret);
2678 if (stat_ret == 0) {
2679 if (saveState)
2680 gStartLdap = START_UNINIT;
2681 retcode = file_move(ldap_file_back, NSCONFIGFILE);
2682 if (mode_verbose)
2683 CLIENT_FPRINTF(stderr,
2684 gettext("recover: file_move(%s, %s)=%d\n"),
2685 ldap_file_back, NSCONFIGFILE, retcode);
2686 if (retcode != 0)
2687 CLIENT_FPRINTF(stderr,
2688 gettext("recover: file_move(%s, %s) failed\n"),
2689 ldap_file_back, NSCONFIGFILE);
2690 }
2691
2692 (void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2693 (void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
2694
2695 stat_ret = stat(ldap_cred_back, &buf);
2696 if (mode_verbose)
2697 CLIENT_FPRINTF(stderr,
2698 gettext("recover: stat(%s)=%d\n"),
2699 ldap_cred_back, stat_ret);
2700 if (stat_ret == 0) {
2701 retcode = file_move(ldap_cred_back, NSCREDFILE);
2702 if (mode_verbose)
2703 CLIENT_FPRINTF(stderr,
2704 gettext("recover: file_move(%s, %s)=%d\n"),
2705 ldap_cred_back, NSCREDFILE, retcode);
2706 if (retcode != 0)
2707 CLIENT_FPRINTF(stderr,
2708 gettext("recover: file_move(%s, %s) failed\n"),
2709 ldap_cred_back, NSCREDFILE);
2710 }
2711
2712 /* Check for recovery of NIS(YP) if we have a domainname */
2713 if (domain) {
2714 /* "name" would have to be huge for this, but just in case */
2715 if (strlen(name) >= (BUFSIZE - strlen(LDAP_RESTORE_DIR)))
2716 return (CLIENT_ERR_FAIL);
2717 if (strlen(name) >= (BUFSIZE - strlen(YP_BIND_DIR)))
2718 return (CLIENT_ERR_FAIL);
2719
2720 (void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2721 (void) strlcat(yp_dir_back, name, BUFSIZE);
2722 stat_ret = stat(yp_dir_back, &buf);
2723 if (mode_verbose)
2724 CLIENT_FPRINTF(stderr,
2725 gettext("recover: stat(%s)=%d\n"),
2726 yp_dir_back, stat_ret);
2727 if (stat_ret == 0) {
2728 (void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
2729 (void) strlcat(yp_dir, name, BUFSIZE);
2730 retcode = file_move(yp_dir_back, yp_dir);
2731 if (mode_verbose)
2732 CLIENT_FPRINTF(stderr,
2733 gettext("recover: file_move(%s, "
2734 "%s)=%d\n"),
2735 yp_dir_back, yp_dir, retcode);
2736 if (retcode != 0) {
2737 CLIENT_FPRINTF(stderr,
2738 gettext("recover: file_move(%s, "
2739 "%s) failed!\n"),
2740 yp_dir_back, yp_dir);
2741 } else {
2742 if (saveState)
2743 gStartYp = START_UNINIT;
2744 }
2745 }
2746 }
2747
2748 /* restore machine configuration */
2749 stat_ret = stat(NSSWITCH_BACK, &buf);
2750 if (mode_verbose)
2751 CLIENT_FPRINTF(stderr,
2752 gettext("recover: stat(%s)=%d\n"),
2753 NSSWITCH_BACK, stat_ret);
2754 if (stat_ret == 0) {
2755 retcode = file_move(NSSWITCH_BACK, NSSWITCH_CONF);
2756 if (mode_verbose)
2757 CLIENT_FPRINTF(stderr,
2758 gettext("recover: file_move(%s, %s)=%d\n"),
2759 NSSWITCH_BACK, NSSWITCH_CONF, retcode);
2760 if (retcode != 0)
2761 CLIENT_FPRINTF(stderr,
2762 gettext("recover: file_move(%s, %s) failed\n"),
2763 NSSWITCH_BACK, NSSWITCH_CONF);
2764 }
2765
2766 stat_ret = stat(DOMAINNAME_BACK, &buf);
2767 if (mode_verbose)
2768 CLIENT_FPRINTF(stderr,
2769 gettext("recover: stat(%s)=%d\n"),
2770 DOMAINNAME_BACK, stat_ret);
2771 if (stat_ret == 0) {
2772 retcode = file_move(DOMAINNAME_BACK, DOMAINNAME);
2773 if (mode_verbose)
2774 CLIENT_FPRINTF(stderr,
2775 gettext("recover: file_move(%s, %s)=%d\n"),
2776 DOMAINNAME_BACK, DOMAINNAME, retcode);
2777 if (retcode != 0)
2778 CLIENT_FPRINTF(stderr,
2779 gettext("recover: file_move(%s, %s) failed\n"),
2780 DOMAINNAME_BACK, DOMAINNAME);
2781 }
2782
2783 retcode = rmdir(LDAP_RESTORE_DIR);
2784 if (retcode != 0) {
2785 CLIENT_FPRINTF(stderr,
2786 gettext("Error removing \"%s\" directory.\n"),
2787 LDAP_RESTORE_DIR);
2788 }
2789
2790 return (CLIENT_SUCCESS);
2791 }
2792
2793 /*
2794 * try to save the current state of this machine.
2795 * this just overwrites any old saved configration files.
2796 *
2797 * This function should only be called after network services have been stopped.
2798 *
2799 * Returns 0 on successful save
2800 * Otherwise returns -1
2801 */
2802 static int
file_backup(void)2803 file_backup(void)
2804 {
2805 struct stat buf;
2806 int domain_stat, conf_stat, ldap_stat;
2807 int yp_stat, restore_stat;
2808 int retcode, namelen, ret;
2809 char yp_dir[BUFSIZ], yp_dir_back[BUFSIZ];
2810 char name[BUFSIZ];
2811 char *ldap_conf_file, *ldap_cred_file;
2812 char ldap_file_back[BUFSIZE], ldap_cred_back[BUFSIZE];
2813
2814 ret = CLIENT_SUCCESS;
2815 /* If running as Sysid Install become a no-op */
2816 if (sysid_install == B_TRUE)
2817 return (CLIENT_SUCCESS);
2818
2819 /* If existing backup files, clear for this run */
2820 restore_stat = stat(LDAP_RESTORE_DIR, &buf);
2821 if (restore_stat == 0) {
2822 if (mode_verbose) {
2823 CLIENT_FPUTS(
2824 gettext("Removing existing restore "
2825 "directory\n"),
2826 stderr);
2827 }
2828 (void) system("/bin/rm -fr " LDAP_RESTORE_DIR);
2829 restore_stat = stat(LDAP_RESTORE_DIR, &buf);
2830 if (restore_stat == 0) {
2831 CLIENT_FPRINTF(stderr,
2832 gettext("Unable to remove backup "
2833 "directory (%s)\n"),
2834 LDAP_RESTORE_DIR);
2835 return (CLIENT_ERR_RESTORE);
2836 }
2837 }
2838
2839 retcode = mkdir(LDAP_RESTORE_DIR, 0755);
2840 if (retcode != 0) {
2841 CLIENT_FPRINTF(stderr,
2842 gettext("file_backup: Failed to make %s backup "
2843 "directory. mkdir=%d\n"),
2844 LDAP_RESTORE_DIR, retcode);
2845 return (CLIENT_ERR_FAIL);
2846 }
2847
2848 conf_stat = stat(NSSWITCH_CONF, &buf);
2849 if (mode_verbose)
2850 CLIENT_FPRINTF(stderr,
2851 gettext("file_backup: stat(%s)=%d\n"),
2852 NSSWITCH_CONF, conf_stat);
2853 if (conf_stat == 0) {
2854 if (mode_verbose)
2855 CLIENT_FPRINTF(stderr,
2856 gettext("file_backup: (%s -> %s)\n"),
2857 NSSWITCH_CONF, NSSWITCH_BACK);
2858 retcode = file_move(NSSWITCH_CONF, NSSWITCH_BACK);
2859 if (retcode != 0) {
2860 CLIENT_FPRINTF(stderr,
2861 gettext("file_backup: file_move(%s, %s) failed "
2862 "with %d\n"),
2863 NSSWITCH_CONF, NSSWITCH_BACK, retcode);
2864 ret = CLIENT_ERR_RENAME;
2865 }
2866 } else {
2867 if (mode_verbose)
2868 CLIENT_FPRINTF(stderr,
2869 gettext("file_backup: No %s file.\n"),
2870 NSSWITCH_CONF);
2871 }
2872
2873 domain_stat = stat(DOMAINNAME, &buf);
2874 if (mode_verbose)
2875 CLIENT_FPRINTF(stderr,
2876 gettext("file_backup: stat(%s)=%d\n"),
2877 DOMAINNAME, domain_stat);
2878 if ((domain_stat == 0) && (buf.st_size > 0)) {
2879 if (mode_verbose)
2880 CLIENT_FPRINTF(stderr,
2881 gettext("file_backup: (%s -> %s)\n"),
2882 DOMAINNAME, DOMAINNAME_BACK);
2883 retcode = file_move(DOMAINNAME, DOMAINNAME_BACK);
2884 if (retcode != 0) {
2885 CLIENT_FPRINTF(stderr,
2886 gettext("file_backup: file_move(%s, %s) failed "
2887 "with %d\n"),
2888 DOMAINNAME, DOMAINNAME_BACK, retcode);
2889 ret = CLIENT_ERR_RENAME;
2890 }
2891 } else {
2892 if (mode_verbose)
2893 if (domain_stat != 0) {
2894 CLIENT_FPRINTF(stderr,
2895 gettext("file_backup: No %s file.\n"),
2896 DOMAINNAME);
2897 } else {
2898 CLIENT_FPRINTF(stderr,
2899 gettext("file_backup: Empty %s "
2900 "file.\n"),
2901 DOMAINNAME);
2902 }
2903 }
2904
2905 namelen = BUFSIZ;
2906 (void) sysinfo(SI_SRPC_DOMAIN, &(name[0]), namelen);
2907 namelen = strlen(name);
2908
2909 if (mode_verbose)
2910 CLIENT_FPRINTF(stderr,
2911 gettext("file_backup: nis domain is \"%s\"\n"),
2912 (namelen > 0) ? name : "EMPTY");
2913 /* check for domain name if not set cannot save NIS(YP) state */
2914 if (namelen > 0) {
2915 /* moving /var/yp/binding will cause ypbind to core dump */
2916 (void) strlcpy(yp_dir, YP_BIND_DIR "/", BUFSIZE);
2917 (void) strlcat(yp_dir, name, BUFSIZE);
2918 yp_stat = stat(yp_dir, &buf);
2919 if (mode_verbose)
2920 CLIENT_FPRINTF(stderr,
2921 gettext("file_backup: stat(%s)=%d\n"),
2922 yp_dir, yp_stat);
2923 if (yp_stat == 0) {
2924 (void) strlcpy(yp_dir_back, LDAP_RESTORE_DIR "/",
2925 BUFSIZE);
2926 (void) strlcat(yp_dir_back, name, BUFSIZE);
2927 if (mode_verbose)
2928 CLIENT_FPRINTF(stderr,
2929 gettext("file_backup: (%s -> %s)\n"),
2930 yp_dir, yp_dir_back);
2931 retcode = file_move(yp_dir, yp_dir_back);
2932 if (retcode != 0) {
2933 CLIENT_FPRINTF(stderr,
2934 gettext("file_backup: file_move(%s, %s)"
2935 " failed with %d\n"),
2936 yp_dir, yp_dir_back, retcode);
2937 ret = CLIENT_ERR_RENAME;
2938 }
2939 } else {
2940 if (mode_verbose)
2941 CLIENT_FPRINTF(stderr,
2942 gettext("file_backup: No %s "
2943 "directory.\n"), yp_dir);
2944 }
2945 }
2946
2947
2948 /* point to file name, not path delim (/) */
2949 ldap_conf_file = strrchr(NSCONFIGFILE, '/') + 1;
2950 ldap_cred_file = strrchr(NSCREDFILE, '/') + 1;
2951
2952 ldap_stat = stat(NSCONFIGFILE, &buf);
2953 if (mode_verbose)
2954 CLIENT_FPRINTF(stderr,
2955 gettext("file_backup: stat(%s)=%d\n"),
2956 NSCONFIGFILE, ldap_stat);
2957 if (ldap_stat == 0) {
2958 (void) strlcpy(ldap_file_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2959 (void) strlcat(ldap_file_back, ldap_conf_file, BUFSIZE);
2960 if (mode_verbose)
2961 CLIENT_FPRINTF(stderr,
2962 gettext("file_backup: (%s -> %s)\n"),
2963 NSCONFIGFILE, ldap_file_back);
2964 retcode = file_move(NSCONFIGFILE, ldap_file_back);
2965 if (retcode != 0) {
2966 CLIENT_FPRINTF(stderr,
2967 gettext("file_backup: file_move(%s, %s) failed "
2968 "with %d\n"),
2969 NSCONFIGFILE, ldap_file_back, retcode);
2970 ret = CLIENT_ERR_RENAME;
2971 }
2972
2973 (void) strlcpy(ldap_cred_back, LDAP_RESTORE_DIR "/", BUFSIZE);
2974 (void) strlcat(ldap_cred_back, ldap_cred_file, BUFSIZE);
2975 if (mode_verbose)
2976 CLIENT_FPRINTF(stderr,
2977 gettext("file_backup: (%s -> %s)\n"),
2978 NSCREDFILE, ldap_cred_back);
2979 retcode = file_move(NSCREDFILE, ldap_cred_back);
2980 if (retcode != 0) {
2981 CLIENT_FPRINTF(stderr,
2982 gettext("file_backup: file_move(%s, %s) failed "
2983 "with %d\n"),
2984 NSCREDFILE, ldap_cred_back, retcode);
2985 ret = CLIENT_ERR_RENAME;
2986 }
2987 } else {
2988 if (mode_verbose)
2989 CLIENT_FPRINTF(stderr,
2990 gettext("file_backup: No %s file.\n"),
2991 NSCONFIGFILE);
2992 }
2993
2994 return (ret);
2995 }
2996
2997 /*
2998 * mod_backup()
2999 *
3000 * This function is used to temporily backup the LDAP client files in /var/ldap
3001 * that the "mod" operation needs to update. If an error occurs then the
3002 * function mod_recover() can be invoke to recover the unmodified files.
3003 */
3004 static int
mod_backup(void)3005 mod_backup(void)
3006 {
3007 int rc;
3008 int retcode = CLIENT_SUCCESS;
3009
3010 rc = system(CMD_CP " " NSCONFIGFILE " " NSCONFIGFILE ".mod");
3011 retcode += rc;
3012 if (mode_verbose)
3013 CLIENT_FPRINTF(stderr,
3014 gettext("mod_backup: backup %s for %s\n"),
3015 rc ? "failed" : "successful", NSCONFIGFILE);
3016
3017 rc = system(CMD_CP " " NSCREDFILE " " NSCREDFILE ".mod");
3018 retcode += rc;
3019 if (mode_verbose)
3020 CLIENT_FPRINTF(stderr,
3021 gettext("mod_backup: backup %s for %s\n"),
3022 rc ? "failed" : "successful", NSCREDFILE);
3023
3024 rc = system(CMD_CP " " DOMAINNAME " " DOMAINNAME ".mod");
3025 retcode += rc;
3026 if (mode_verbose)
3027 CLIENT_FPRINTF(stderr,
3028 gettext("mod_backup: backup %s for %s\n"),
3029 rc ? "failed" : "successful", DOMAINNAME);
3030
3031 if (retcode != CLIENT_SUCCESS)
3032 retcode = CLIENT_ERR_RENAME;
3033 return (retcode);
3034 }
3035
3036 /*
3037 * mod_recover()
3038 *
3039 * This function is used to recover the temporily backed up files by
3040 * the mod_backup() function if an error occurs during the "mod"
3041 * operation.
3042 */
3043 static int
mod_recover(void)3044 mod_recover(void)
3045 {
3046 int rc;
3047 int retcode = CLIENT_SUCCESS;
3048
3049 rc = system(CMD_MV " " NSCONFIGFILE ".mod " NSCONFIGFILE);
3050 retcode += rc;
3051 if (mode_verbose)
3052 CLIENT_FPRINTF(stderr,
3053 gettext("mod_recover: recovery %s for %s\n"),
3054 rc ? "failed" : "successful", NSCONFIGFILE);
3055
3056 rc = system(CMD_MV " " NSCREDFILE ".mod " NSCREDFILE);
3057 retcode += rc;
3058 if (mode_verbose)
3059 CLIENT_FPRINTF(stderr,
3060 gettext("mod_recover: recovery %s for %s\n"),
3061 rc ? "failed" : "successful", NSCREDFILE);
3062
3063 rc = system(CMD_MV " " DOMAINNAME ".mod " DOMAINNAME);
3064 retcode += rc;
3065 if (mode_verbose)
3066 CLIENT_FPRINTF(stderr,
3067 gettext("mod_recover: recovery %s for %s\n"),
3068 rc ? "failed" : "successful", DOMAINNAME);
3069
3070 if (retcode != CLIENT_SUCCESS)
3071 retcode = CLIENT_ERR_RENAME;
3072 return (retcode);
3073 }
3074
3075 /*
3076 * mod_cleanup()
3077 *
3078 * This function removes the .mod files in /var/ldap.
3079 */
3080 static void
mod_cleanup(void)3081 mod_cleanup(void)
3082 {
3083 (void) system(CMD_RM " " NSCONFIGFILE ".mod " TO_DEV_NULL);
3084 (void) system(CMD_RM " " NSCREDFILE ".mod " TO_DEV_NULL);
3085 (void) system(CMD_RM " " DOMAINNAME ".mod " TO_DEV_NULL);
3086 }
3087
3088 #define MAX_DN_ARRAY 100
3089 #define LDAP_NAMINGCONTEXTS "namingcontexts"
3090
3091 static multival_t *
multival_new()3092 multival_new()
3093 {
3094 multival_t *hold;
3095
3096 hold = calloc(1, sizeof (multival_t));
3097 if (hold == NULL) {
3098 CLIENT_FPUTS(
3099 gettext("multival_new: Memory allocation error\n"),
3100 stderr);
3101 }
3102 return (hold); /* NULL -> error */
3103 }
3104
3105 static int
multival_add(multival_t * list,char * opt)3106 multival_add(multival_t *list, char *opt)
3107 {
3108 if (opt == NULL) {
3109 CLIENT_FPUTS(
3110 gettext("Empty value passed to multival_add\n"),
3111 stderr);
3112 return (CLIENT_ERR_FAIL);
3113 }
3114
3115 if (list->count == 0) {
3116 list->optlist = (char **)malloc(sizeof (char **));
3117 } else {
3118 list->optlist = (char **)realloc(list->optlist,
3119 (list->count + 1) * sizeof (char **));
3120 }
3121
3122 if (list->optlist == NULL) {
3123 CLIENT_FPUTS(gettext("Error allocating memory\n"), stderr);
3124 return (CLIENT_ERR_MEMORY); /* 0 is success */
3125 }
3126
3127 list->optlist[list->count] = opt;
3128 list->count++;
3129
3130 return (CLIENT_SUCCESS);
3131 }
3132
3133 static void
multival_free(multival_t * list)3134 multival_free(multival_t *list)
3135 {
3136 if (list == NULL)
3137 return;
3138
3139 if (list->optlist != NULL)
3140 free(list->optlist);
3141 free(list);
3142 }
3143
3144 static clientopts_t *
clientopts_new()3145 clientopts_new()
3146 {
3147 clientopts_t *hold;
3148
3149 hold = calloc(1, sizeof (clientopts_t));
3150 if (NULL == hold) {
3151 CLIENT_FPUTS(gettext("Error allocating memory for "
3152 "clientopts structure\n"), stderr);
3153 return (hold); /* NULL -> error */
3154 }
3155
3156 hold->serviceAuthenticationMethod = multival_new();
3157 if (NULL == hold->serviceAuthenticationMethod) {
3158 CLIENT_FPUTS(gettext("Error allocating memory for "
3159 "serviceAuthenticationMethod\n"), stderr);
3160 free(hold);
3161 return (NULL); /* NULL -> error */
3162 }
3163
3164 hold->serviceCredentialLevel = multival_new();
3165 if (NULL == hold->serviceCredentialLevel) {
3166 CLIENT_FPUTS(gettext("Error allocating memory for "
3167 "serviceCredentialLevel\n"), stderr);
3168 multival_free(hold->serviceAuthenticationMethod);
3169 free(hold);
3170 return (NULL); /* NULL -> error */
3171 }
3172
3173 hold->objectclassMap = multival_new();
3174 if (NULL == hold->objectclassMap) {
3175 CLIENT_FPUTS(gettext("Error allocating memory for "
3176 "objectclassMap\n"), stderr);
3177 multival_free(hold->serviceAuthenticationMethod);
3178 multival_free(hold->serviceCredentialLevel);
3179 free(hold);
3180 return (NULL); /* NULL -> error */
3181 }
3182
3183 hold->attributeMap = multival_new();
3184 if (NULL == hold->attributeMap) {
3185 CLIENT_FPUTS(gettext("Error allocating memory for "
3186 "attributeMap\n"), stderr);
3187 multival_free(hold->serviceAuthenticationMethod);
3188 multival_free(hold->serviceCredentialLevel);
3189 multival_free(hold->objectclassMap);
3190 free(hold);
3191 return (NULL); /* NULL -> error */
3192 }
3193
3194 hold->serviceSearchDescriptor = multival_new();
3195 if (NULL == hold->serviceSearchDescriptor) {
3196 CLIENT_FPUTS(gettext("Error allocating memory for "
3197 "serviceSearchDescriptor\n"), stderr);
3198 multival_free(hold->serviceAuthenticationMethod);
3199 multival_free(hold->serviceCredentialLevel);
3200 multival_free(hold->objectclassMap);
3201 multival_free(hold->attributeMap);
3202 free(hold);
3203 return (NULL); /* NULL -> error */
3204 }
3205
3206 return (hold);
3207 }
3208
3209 static void
clientopts_free(clientopts_t * list)3210 clientopts_free(clientopts_t *list)
3211 {
3212 if (NULL == list)
3213 return;
3214
3215 multival_free(list->serviceAuthenticationMethod);
3216 multival_free(list->serviceCredentialLevel);
3217 multival_free(list->objectclassMap);
3218 multival_free(list->attributeMap);
3219 multival_free(list->serviceSearchDescriptor);
3220
3221 free(list);
3222
3223 }
3224
3225 static void
multival_list(char * opt,multival_t * list)3226 multival_list(char *opt, multival_t *list)
3227 {
3228 int i;
3229
3230 if (list->count == 0)
3231 return;
3232
3233 (void) puts(opt);
3234 for (i = 0; i < list->count; i++) {
3235 (void) printf("\t\targ[%d]: %s\n", i, list->optlist[i]);
3236 }
3237 }
3238
3239 /* return the number of arguments specified in the command line */
3240 static int
num_args(clientopts_t * list)3241 num_args(clientopts_t *list)
3242 {
3243 int arg_count = 0;
3244
3245 arg_count += list->authenticationMethod ? 1 : 0;
3246 arg_count += list->serviceAuthenticationMethod->count;
3247 arg_count += list->defaultSearchBase ? 1 : 0;
3248 arg_count += list->credentialLevel ? 1 : 0;
3249 arg_count += list->serviceCredentialLevel->count;
3250 arg_count += list->domainName ? 1 : 0;
3251 arg_count += list->proxyDN ? 1 : 0;
3252 arg_count += list->enableShadowUpdate ? 1 : 0;
3253 arg_count += list->adminDN ? 1 : 0;
3254 arg_count += list->profileTTL ? 1 : 0;
3255 arg_count += list->objectclassMap->count;
3256 arg_count += list->searchTimeLimit ? 1 : 0;
3257 arg_count += list->preferredServerList ? 1 : 0;
3258 arg_count += list->profileName ? 1 : 0;
3259 arg_count += list->followReferrals ? 1 : 0;
3260 arg_count += list->attributeMap->count;
3261 arg_count += list->defaultSearchScope ? 1 : 0;
3262 arg_count += list->serviceSearchDescriptor->count;
3263 arg_count += list->bindTimeLimit ? 1 : 0;
3264 arg_count += list->proxyPassword ? 1 : 0;
3265 arg_count += list->adminPassword ? 1 : 0;
3266 arg_count += list->defaultServerList ? 1 : 0;
3267 arg_count += list->certificatePath ? 1 : 0;
3268
3269 return (arg_count);
3270 }
3271
3272 #define CLIENT_PRINT(opt, str) if (str) \
3273 (void) printf("%s%s\n", (opt), (str))
3274
3275 static void
dumpargs(clientopts_t * list)3276 dumpargs(clientopts_t *list)
3277 {
3278 CLIENT_PRINT("\tauthenticationMethod: ", list->authenticationMethod);
3279 multival_list("\tserviceAuthenticationMethod: ",
3280 list->serviceAuthenticationMethod);
3281 CLIENT_PRINT("\tdefaultSearchBase: ", list->defaultSearchBase);
3282 CLIENT_PRINT("\tcredentialLevel: ", list->credentialLevel);
3283 multival_list("\tserviceCredentialLevel: ",
3284 list->serviceCredentialLevel);
3285 CLIENT_PRINT("\tdomainName: ", list->domainName);
3286 CLIENT_PRINT("\tproxyDN: ", list->proxyDN);
3287 CLIENT_PRINT("\tadminDN: ", list->adminDN);
3288 CLIENT_PRINT("\tenableShadowUpdate: ", list->enableShadowUpdate);
3289 CLIENT_PRINT("\tprofileTTL: ", list->profileTTL);
3290 multival_list("\tobjectclassMap: ", list->objectclassMap);
3291 CLIENT_PRINT("\tsearchTimeLimit: ", list->searchTimeLimit);
3292 CLIENT_PRINT("\tpreferredServerList: ", list->preferredServerList);
3293 CLIENT_PRINT("\tprofileName: ", list->profileName);
3294 CLIENT_PRINT("\tfollowReferrals: ", list->followReferrals);
3295 multival_list("\tattributeMap: ", list->attributeMap);
3296 CLIENT_PRINT("\tdefaultSearchScope: ", list->defaultSearchScope);
3297 multival_list("\tserviceSearchDescriptor: ",
3298 list->serviceSearchDescriptor);
3299 CLIENT_PRINT("\tbindTimeLimit: ", list->bindTimeLimit);
3300 CLIENT_PRINT("\tproxyPassword: ", list->proxyPassword);
3301 CLIENT_PRINT("\tadminPassword: ", list->adminPassword);
3302 CLIENT_PRINT("\tdefaultServerList: ", list->defaultServerList);
3303 CLIENT_PRINT("\tcertificatePath: ", list->certificatePath);
3304 }
3305
3306
3307 /* These definitions are only used in parseParam() below. */
3308 struct param {
3309 char *name;
3310 int index;
3311 };
3312
3313 static struct param paramArray[] = {
3314 {"proxyDN", NS_LDAP_BINDDN_P},
3315 {"proxyPassword", NS_LDAP_BINDPASSWD_P},
3316 {"defaultServerList", NS_LDAP_SERVERS_P},
3317 {"defaultSearchBase", NS_LDAP_SEARCH_BASEDN_P},
3318 {"authenticationMethod", NS_LDAP_AUTH_P},
3319 {"followReferrals", NS_LDAP_SEARCH_REF_P},
3320 {"profileTTL", NS_LDAP_CACHETTL_P},
3321 {"certificatePath", NS_LDAP_HOST_CERTPATH_P},
3322 {"defaultSearchScope", NS_LDAP_SEARCH_SCOPE_P},
3323 {"bindTimeLimit", NS_LDAP_BIND_TIME_P},
3324 {"searchTimeLimit", NS_LDAP_SEARCH_TIME_P},
3325 {"preferredServerList", NS_LDAP_SERVER_PREF_P},
3326 {"profileName", NS_LDAP_PROFILE_P},
3327 {"credentialLevel", NS_LDAP_CREDENTIAL_LEVEL_P},
3328 {"serviceSearchDescriptor", NS_LDAP_SERVICE_SEARCH_DESC_P},
3329 {"attributeMap", NS_LDAP_ATTRIBUTEMAP_P},
3330 {"objectclassMap", NS_LDAP_OBJECTCLASSMAP_P},
3331 {"serviceAuthenticationMethod", NS_LDAP_SERVICE_AUTH_METHOD_P},
3332 {"serviceCredentialLevel", NS_LDAP_SERVICE_CRED_LEVEL_P},
3333 {"domainName", LOCAL_DOMAIN_P},
3334 {"enableShadowUpdate", NS_LDAP_ENABLE_SHADOW_UPDATE_P},
3335 {"adminDN", NS_LDAP_ADMIN_BINDDN_P},
3336 {"adminPassword", NS_LDAP_ADMIN_BINDPASSWD_P},
3337 {NULL, 0}
3338 };
3339
3340 static int
parseParam(char * param,char ** paramVal)3341 parseParam(char *param, char **paramVal)
3342 {
3343 char *val = NULL;
3344 int counter;
3345
3346 if (mode_verbose) {
3347 CLIENT_FPRINTF(stderr, gettext("Parsing %s\n"), param);
3348 }
3349
3350 val = strchr(param, '=');
3351 if (val == NULL) {
3352 CLIENT_FPUTS(
3353 gettext("Didn\'t find \'=\' character in string\n"),
3354 stderr);
3355 paramVal = NULL;
3356 return (CLIENT_ERR_PARSE);
3357 }
3358
3359 *val = '\0';
3360
3361 for (counter = 0; paramArray[counter].name != NULL; counter++) {
3362 if (strcasecmp(paramArray[counter].name, param) == 0) {
3363 *paramVal = val+1;
3364 *val = '='; /* restore original param */
3365 return (paramArray[counter].index);
3366 }
3367 }
3368
3369 /* Not found */
3370 *val = '='; /* restore original param */
3371 *paramVal = NULL;
3372 return (CLIENT_ERR_PARSE);
3373 }
3374
3375 /*
3376 * The following macro checks if an option has already been specified
3377 * and errs out with usage if so
3378 */
3379 #define CLIENT_OPT_CHECK(opt, optarg) \
3380 if (optarg) { \
3381 CLIENT_FPUTS(gettext("Invalid use of option\n"), stderr); \
3382 usage(); \
3383 clientopts_free(optlist); \
3384 return (CLIENT_ERR_FAIL); \
3385 }
3386
3387 static int
clientSetParam(clientopts_t * optlist,int paramFlag,char * attrVal)3388 clientSetParam(clientopts_t *optlist, int paramFlag, char *attrVal)
3389 {
3390 int retcode = 0;
3391 int counter;
3392
3393
3394 switch (paramFlag) {
3395 case NS_LDAP_AUTH_P:
3396 CLIENT_OPT_CHECK(paramFlag, optlist->authenticationMethod);
3397 optlist->authenticationMethod = attrVal;
3398 break;
3399
3400 case NS_LDAP_SERVICE_AUTH_METHOD_P: /* multiple allowed */
3401 retcode = multival_add(optlist->serviceAuthenticationMethod,
3402 attrVal);
3403 if (retcode != CLIENT_SUCCESS) {
3404 CLIENT_FPRINTF(stderr,
3405 gettext("Error processing attrVal %s\n"),
3406 attrVal?attrVal:"NULL");
3407 usage();
3408 clientopts_free(optlist);
3409 return (CLIENT_ERR_FAIL);
3410 }
3411 break;
3412
3413 case NS_LDAP_SEARCH_BASEDN_P:
3414 CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchBase);
3415 optlist->defaultSearchBase = attrVal;
3416 break;
3417
3418 case NS_LDAP_CREDENTIAL_LEVEL_P:
3419 CLIENT_OPT_CHECK(paramFlag, optlist->credentialLevel);
3420 optlist->credentialLevel = attrVal;
3421 break;
3422
3423 case NS_LDAP_SERVICE_CRED_LEVEL_P: /* multiple allowed */
3424 retcode = multival_add(optlist->serviceCredentialLevel,
3425 attrVal);
3426 if (retcode != CLIENT_SUCCESS) {
3427 CLIENT_FPRINTF(stderr,
3428 gettext("Error processing attrVal %s\n"),
3429 attrVal?attrVal:"NULL");
3430 usage();
3431 clientopts_free(optlist);
3432 return (CLIENT_ERR_FAIL);
3433 }
3434 break;
3435
3436 case LOCAL_DOMAIN_P:
3437 CLIENT_OPT_CHECK(paramFlag, optlist->domainName);
3438 optlist->domainName = attrVal;
3439 dname = optlist->domainName;
3440 break;
3441
3442 case NS_LDAP_BINDDN_P:
3443 CLIENT_OPT_CHECK(paramFlag, optlist->proxyDN);
3444 optlist->proxyDN = attrVal;
3445 break;
3446
3447 case NS_LDAP_ENABLE_SHADOW_UPDATE_P:
3448 CLIENT_OPT_CHECK(paramFlag, optlist->enableShadowUpdate);
3449 optlist->enableShadowUpdate = attrVal;
3450 break;
3451
3452 case NS_LDAP_ADMIN_BINDDN_P:
3453 CLIENT_OPT_CHECK(paramFlag, optlist->adminDN);
3454 optlist->adminDN = attrVal;
3455 break;
3456
3457 case NS_LDAP_CACHETTL_P:
3458 CLIENT_OPT_CHECK(paramFlag, optlist->profileTTL);
3459 optlist->profileTTL = attrVal;
3460 break;
3461
3462 case NS_LDAP_OBJECTCLASSMAP_P: /* multiple allowed */
3463 retcode = multival_add(optlist->objectclassMap, attrVal);
3464 if (retcode != CLIENT_SUCCESS) {
3465 CLIENT_FPRINTF(stderr,
3466 gettext("Error processing attrVal %s\n"),
3467 attrVal?attrVal:"NULL");
3468 usage();
3469 clientopts_free(optlist);
3470 return (CLIENT_ERR_FAIL);
3471 }
3472 break;
3473
3474 case NS_LDAP_SEARCH_TIME_P:
3475 CLIENT_OPT_CHECK(paramFlag, optlist->searchTimeLimit);
3476 optlist->searchTimeLimit = attrVal;
3477 break;
3478
3479 case NS_LDAP_SERVER_PREF_P:
3480 CLIENT_OPT_CHECK(paramFlag, optlist->preferredServerList);
3481 optlist->preferredServerList = attrVal;
3482 /* replace ',' chars with ' ' for proper syntax */
3483 for (counter = 0;
3484 counter < strlen(optlist->preferredServerList);
3485 counter++) {
3486
3487 if (optlist->preferredServerList[counter] == ',')
3488 optlist->preferredServerList[counter] = ' ';
3489 }
3490 break;
3491
3492 case NS_LDAP_PROFILE_P:
3493 CLIENT_OPT_CHECK(paramFlag, optlist->profileName);
3494 optlist->profileName = attrVal;
3495 break;
3496
3497 case NS_LDAP_SEARCH_REF_P:
3498 CLIENT_OPT_CHECK(paramFlag, optlist->followReferrals);
3499 if (0 == strcasecmp(attrVal, "followref"))
3500 optlist->followReferrals = "TRUE";
3501 else if (0 == strcasecmp(attrVal, "noref"))
3502 optlist->followReferrals = "FALSE";
3503 else
3504 optlist->followReferrals = attrVal;
3505 break;
3506
3507 case NS_LDAP_ATTRIBUTEMAP_P: /* multiple allowed */
3508 retcode = multival_add(optlist->attributeMap, attrVal);
3509 if (retcode != CLIENT_SUCCESS) {
3510 CLIENT_FPRINTF(stderr,
3511 gettext("Error processing attrVal %s\n"),
3512 attrVal?attrVal:"NULL");
3513 usage();
3514 clientopts_free(optlist);
3515 return (CLIENT_ERR_FAIL);
3516 }
3517 break;
3518
3519 case NS_LDAP_SEARCH_SCOPE_P:
3520 CLIENT_OPT_CHECK(paramFlag, optlist->defaultSearchScope);
3521 optlist->defaultSearchScope = attrVal;
3522 break;
3523
3524 case NS_LDAP_SERVICE_SEARCH_DESC_P: /* multiple allowed */
3525 retcode = multival_add(optlist->serviceSearchDescriptor,
3526 attrVal);
3527 if (retcode != CLIENT_SUCCESS) {
3528 CLIENT_FPRINTF(stderr,
3529 gettext("Error processing attrVal %s\n"),
3530 attrVal?attrVal:"NULL");
3531 usage();
3532 clientopts_free(optlist);
3533 return (CLIENT_ERR_FAIL);
3534 }
3535 break;
3536
3537 case NS_LDAP_BIND_TIME_P:
3538 CLIENT_OPT_CHECK(paramFlag, optlist->bindTimeLimit);
3539 optlist->bindTimeLimit = attrVal;
3540 break;
3541
3542 case NS_LDAP_BINDPASSWD_P:
3543 CLIENT_OPT_CHECK(paramFlag, optlist->proxyPassword);
3544 optlist->proxyPassword = attrVal;
3545 break;
3546
3547 case NS_LDAP_ADMIN_BINDPASSWD_P:
3548 CLIENT_OPT_CHECK(paramFlag, optlist->adminPassword);
3549 optlist->adminPassword = attrVal;
3550 break;
3551
3552 case NS_LDAP_HOST_CERTPATH_P:
3553 CLIENT_OPT_CHECK(paramFlag, optlist->certificatePath);
3554 optlist->certificatePath = attrVal;
3555 break;
3556
3557 case NS_LDAP_SERVERS_P:
3558 CLIENT_OPT_CHECK(paramFlag, optlist->defaultServerList);
3559 optlist->defaultServerList = attrVal;
3560 break;
3561
3562 default:
3563 usage();
3564 return (CLIENT_ERR_FAIL);
3565 /* break; lint doesn't like break before end of switch */
3566 }
3567
3568 return (retcode);
3569 }
3570
3571 /*
3572 * file_move() - Used to move a config file (backup/restore).
3573 *
3574 * This function uses a system() call with /bin/mv to handle the
3575 * case where the backup directory (/var) is on a different file
3576 * system than the config file (typically /etc).
3577 */
3578 static int
file_move(const char * from,const char * to)3579 file_move(const char *from, const char *to)
3580 {
3581 int retcode;
3582 char mvCommand[] = CMD_MV;
3583 char cmd_buffer[(2 * MAXPATHLEN) + sizeof (mvCommand) + 3];
3584
3585 (void) snprintf(cmd_buffer, sizeof (cmd_buffer), "%s %s %s",
3586 mvCommand, from, to);
3587
3588 /*
3589 * This function should only be used internally to move
3590 * system files to/from the backup directory. For security
3591 * reasons (this is run as root), don't use this function
3592 * with arguments passed into the program.
3593 */
3594 retcode = system(cmd_buffer);
3595
3596 return (retcode);
3597 }
3598
3599
3600 /*
3601 * Manipulate the service as instructed by "dowhat"
3602 */
3603 static int
do_service(const char * fmri,boolean_t waitflag,int dowhat,const char * state)3604 do_service(const char *fmri, boolean_t waitflag, int dowhat,
3605 const char *state) {
3606
3607 int status;
3608 boolean_t is_maint;
3609 const char *what = gettext("not set");
3610 useconds_t max;
3611
3612 /* Check if we are in maintenance */
3613 is_maint = is_service(fmri, SCF_STATE_STRING_MAINT);
3614
3615 switch (dowhat) {
3616 case START_SERVICE:
3617 what = gettext("start");
3618 status = smf_enable_instance(fmri,
3619 (sysid_install == B_TRUE)?SMF_TEMPORARY:0);
3620 break;
3621 case STOP_SERVICE:
3622 what = gettext("stop");
3623 status = smf_disable_instance(fmri,
3624 (sysid_install == B_TRUE)?SMF_TEMPORARY:0);
3625 break;
3626 case RESTART_SERVICE:
3627 what = gettext("restart");
3628 status = smf_restart_instance(fmri);
3629 break;
3630 default:
3631 /* coding error; will not happen */
3632 assert(0);
3633 }
3634
3635 /*
3636 * If the service was previously in maintenance then we need to
3637 * clear it immediately. The "dowhat" action will set the
3638 * enabled property of the service as intended by the caller while
3639 * clear will actually cause it to be enabled/disabled.
3640 * We assume that the caller has called us after taking some
3641 * recovery action. Even if it's not the case, we don't lose
3642 * anything.
3643 */
3644 if (status == 0 && is_maint == B_TRUE) {
3645 if (mode_verbose)
3646 CLIENT_FPRINTF(stderr,
3647 "%s: %s... %s\n",
3648 what,
3649 fmri,
3650 gettext("restoring from maintenance state"));
3651 status = smf_restore_instance(fmri);
3652 }
3653
3654 if (status == 0) {
3655 /* Check if we need to wait ? */
3656 if (waitflag == B_FALSE) {
3657 if (mode_verbose)
3658 CLIENT_FPRINTF(stderr,
3659 "%s: %s... %s\n",
3660 what,
3661 fmri,
3662 gettext("success"));
3663 return (CLIENT_SUCCESS);
3664 }
3665
3666 /* Otherwise wait for max seconds (from the manifest) */
3667 max = get_timeout_value(dowhat, fmri, DEFAULT_TIMEOUT);
3668 status = wait_till(fmri, state, max, what, !is_maint);
3669 if (status == CLIENT_SUCCESS)
3670 return (CLIENT_SUCCESS);
3671 /* For error fall through for corrective action */
3672 } else {
3673 /* Well, service failed ... */
3674 if (mode_verbose)
3675 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3676 what,
3677 fmri,
3678 gettext("failed"),
3679 scf_strerror(scf_error()));
3680 status = CLIENT_ERR_FAIL;
3681 /* For error fall through for corrective action */
3682 }
3683
3684 /*
3685 * If service is still offline after start/restart, then transitioning
3686 * failed and guess is restarter failed to apply the timeout as well.
3687 * So instead of leaving it offline, let's just disable it until we have
3688 * some other mechanism available from smf to handle such situation.
3689 */
3690 if (dowhat != STOP_SERVICE)
3691 if (is_service(fmri, SCF_STATE_STRING_OFFLINE)) {
3692 if (mode_verbose)
3693 CLIENT_FPRINTF(stderr,
3694 "%s: %s... %s\n",
3695 what,
3696 fmri,
3697 gettext("offline to disable"));
3698 (void) disable_service(fmri, waitflag);
3699 }
3700
3701 return (status);
3702 }
3703
3704
3705 /*
3706 * Wait for "max" usecs for the service described by "fmri" to change
3707 * to "state". If check_maint is true then return immediately if
3708 * service goes into maintenance
3709 */
3710 static int
wait_till(const char * fmri,const char * state,useconds_t max,const char * what,boolean_t check_maint)3711 wait_till(const char *fmri, const char *state, useconds_t max,
3712 const char *what, boolean_t check_maint) {
3713 char *st;
3714 useconds_t usecs = INIT_WAIT_USECS;
3715
3716 for (; max > 0; max -= usecs) {
3717 /* incremental wait */
3718 usecs *= 2;
3719 usecs = (usecs > max)?max:usecs;
3720 if (mode_verbose)
3721 CLIENT_FPRINTF(stderr,
3722 "%s: %s %u %s\n",
3723 what, gettext("sleep"), usecs,
3724 gettext("microseconds"));
3725 (void) usleep(usecs);
3726
3727 /* Check state after the wait */
3728 if ((st = smf_get_state(fmri)) != NULL) {
3729 if (strcmp(st, state) == 0) {
3730 if (mode_verbose)
3731 CLIENT_FPRINTF(stderr,
3732 "%s: %s... %s\n",
3733 what,
3734 fmri,
3735 gettext("success"));
3736 free(st);
3737 return (CLIENT_SUCCESS);
3738 }
3739
3740 /*
3741 * If service has gone into maintenance then
3742 * we will time out anyway, so we are better
3743 * off returning now
3744 */
3745 if (check_maint &&
3746 strcmp(st, SCF_STATE_STRING_MAINT) == 0) {
3747 if (mode_verbose)
3748 CLIENT_FPRINTF(stderr,
3749 "%s: %s... %s\n",
3750 what,
3751 fmri,
3752 gettext("maintenance"));
3753 free(st);
3754 return (CLIENT_ERR_MAINTENANCE);
3755 }
3756 free(st);
3757 } else {
3758 if (mode_verbose)
3759 CLIENT_FPRINTF(stderr,
3760 "%s: %s... %s: %s\n",
3761 what,
3762 fmri,
3763 gettext("failed"),
3764 scf_strerror(scf_error()));
3765 return (CLIENT_ERR_FAIL);
3766 }
3767 }
3768
3769 /* Timed out waiting */
3770 if (mode_verbose)
3771 CLIENT_FPRINTF(stderr,
3772 "%s: %s... %s\n",
3773 what,
3774 fmri,
3775 gettext("timed out"));
3776 return (CLIENT_ERR_TIMEDOUT);
3777 }
3778
3779
3780 static boolean_t
is_service(const char * fmri,const char * state)3781 is_service(const char *fmri, const char *state) {
3782 char *st;
3783 boolean_t result = B_FALSE;
3784
3785 if ((st = smf_get_state(fmri)) != NULL) {
3786 if (strcmp(st, state) == 0)
3787 result = B_TRUE;
3788 free(st);
3789 }
3790 return (result);
3791 }
3792
3793
3794 /*
3795 *
3796 * get_timeout_val : returns the timeout value set in fmri manifest
3797 * inputs : action(start/stop)
3798 * fmri(defined fmri string)
3799 * Returns default if error, the timeout val otherwise
3800 *
3801 */
3802
3803 static useconds_t
get_timeout_value(int dowhat,const char * fmri,useconds_t default_val)3804 get_timeout_value(int dowhat, const char *fmri, useconds_t default_val)
3805 {
3806 scf_simple_prop_t *sp = NULL;
3807 uint64_t *cp = NULL;
3808 int timeout = default_val/1000000;
3809 char *action = NULL;
3810 const char *actionstr = NULL;
3811
3812 switch (dowhat) {
3813 case START_SERVICE:
3814 case RESTART_SERVICE:
3815 action = "start";
3816 actionstr = gettext("start");
3817 break;
3818 case STOP_SERVICE:
3819 action = "stop";
3820 actionstr = gettext("stop");
3821 break;
3822 default:
3823 assert(0);
3824 }
3825
3826
3827 sp = scf_simple_prop_get(NULL, fmri, action, SCF_PROPERTY_TIMEOUT);
3828 if (sp == NULL) {
3829 if (mode_verbose)
3830 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3831 actionstr,
3832 fmri,
3833 gettext("failed to retrieve timeout property"),
3834 scf_strerror(scf_error()));
3835 return (default_val);
3836 }
3837
3838 cp = scf_simple_prop_next_count(sp);
3839 if (cp == NULL) {
3840 if (mode_verbose)
3841 CLIENT_FPRINTF(stderr, "%s: %s... %s: %s\n",
3842 actionstr,
3843 fmri,
3844 gettext("failed to retrieve timeout value"),
3845 scf_strerror(scf_error()));
3846 scf_simple_prop_free(sp);
3847 return (default_val);
3848 }
3849
3850 if (*cp != 0)
3851 timeout = *cp;
3852 scf_simple_prop_free(sp);
3853 return (timeout * 1000000);
3854 }
3855