From: Greg Hudson Date: Fri, 30 Jan 2015 17:48:15 +0000 (-0500) Subject: Support kadmin script mode X-Git-Tag: krb5-1.14-alpha1~163 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=040fe97758bdf53b6c00815b0306410eb88ea5ec;p=thirdparty%2Fkrb5.git Support kadmin script mode Add support for a command and argments to be specified on the kadmin command line, with script-friendly behavior. kadmin_startup() now yields either a request string or a request argv array, and sets script_mode in the argv array case. Informational messages now go through info() and are suppressed if script_mode is set. Prompts and warning messages are also suppressed in script mode. Error messages indicating a failure now go through error() and set exit_status if script_mode is set. The extended com_err() hook is always installed so that com_err messages go through error() and set exit_status. getopt() is now invoked with a leading '+' to suppress Gnu getopt argument reordering behavior, so that invokers don't need to pass "--" to prevent query options from being treated as kadmin options. Non-Gnu getopt implementations should harmlessly treat '+' as a valid flag option, which has no effect as it will reach the same default label in the switch statement. ticket: 7991 --- diff --git a/doc/admin/admin_commands/kadmin_local.rst b/doc/admin/admin_commands/kadmin_local.rst index faf7105905..5572b34cc7 100644 --- a/doc/admin/admin_commands/kadmin_local.rst +++ b/doc/admin/admin_commands/kadmin_local.rst @@ -16,6 +16,7 @@ SYNOPSIS [[**-c** *cache_name*]\|[**-k** [**-t** *keytab*]]\|\ **-n**] [**-w** *password*] [**-s** *admin_server*\ [:*port*]] +[command args...] **kadmin.local** [**-r** *realm*] @@ -25,6 +26,7 @@ SYNOPSIS [**-e** *enc*:*salt* ...] [**-m**] [**-x** *db_args*] +[command args...] .. _kadmin_synopsis_end: @@ -112,8 +114,7 @@ OPTIONS via the process list. **-q** *query* - Perform the specified query and then exit. This can be useful for - writing scripts. + Perform the specified query and then exit. **-d** *dbname* Specifies the name of the KDC database. This option does not @@ -143,6 +144,24 @@ OPTIONS .. _kadmin_options_end: +Starting with release 1.14, if any command-line arguments remain after +the options, they will be treated as a single query to be executed. +This mode of operation is intended for scripts and behaves differently +from the interactive mode in several respects: + +* Query arguments are split by the shell, not by kadmin. +* Informational and warning messages are suppressed. Error messages + and query output (e.g. for **get_principal**) will still be + displayed. +* Confirmation prompts are disabled (as if **-force** was given). + Password prompts will still be issued as required. +* The exit status will be non-zero if the query fails. + +The **-q** option does not carry these behavior differences; the query +will be processed as if it was entered interactively. The **-q** +option cannot be used in combination with a query in the remaining +arguments. + .. _dboptions: DATABASE OPTIONS diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index a81036cdbb..defc0fe9f4 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -101,6 +101,7 @@ static char *prflags[] = { "NO_AUTH_DATA_REQUIRED", /* 0x00400000 */ }; +static krb5_boolean script_mode = FALSE; int exit_status = 0; char *def_realm = NULL; char *whoami = NULL; @@ -111,20 +112,60 @@ char *ccache_name = NULL; int locked = 0; +static void +info(const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +static void +error(const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +/* Like printf, but suppressed if script_mode is set. */ +static void +info(const char *fmt, ...) +{ + va_list ap; + + if (script_mode) + return; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +/* Like fprintf to stderr; also set exit_status if script_mode is set. */ +static void +error(const char *fmt, ...) +{ + va_list ap; + + if (script_mode) + exit_status = 1; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + static void usage() { - fprintf(stderr, - _("Usage: %s [-r realm] [-p principal] [-q query] " - "[clnt|local args]\n" - "\tclnt args: [-s admin_server[:port]] " - "[[-c ccache]|[-k [-t keytab]]]|[-n]\n" - "\tlocal args: [-x db_args]* [-d dbname] " - "[-e \"enc:salt ...\"] [-m]\n" - "where,\n\t[-x db_args]* - any number of database specific " - "arguments.\n" - "\t\t\tLook at each database documentation for supported " - "arguments\n"), whoami); + error(_("Usage: %s [-r realm] [-p principal] [-q query] " + "[clnt|local args]\n" + " [command args...]\n" + "\tclnt args: [-s admin_server[:port]] " + "[[-c ccache]|[-k [-t keytab]]]|[-n]\n" + "\tlocal args: [-x db_args]* [-d dbname] " + "[-e \"enc:salt ...\"] [-m]" + "where,\n\t[-x db_args]* - any number of database specific " + "arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n"), whoami); exit(1); } @@ -200,13 +241,13 @@ extended_com_err_fn(const char *myprog, errcode_t code, if (code) { emsg = krb5_get_error_message(context, code); - fprintf(stderr, "%s: %s ", myprog, emsg); + error("%s: %s ", myprog, emsg); krb5_free_error_message(context, emsg); } else { - fprintf(stderr, "%s: ", myprog); + error("%s: ", myprog); } vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); + error("\n"); } /* Create a principal using the oldest appropriate kadm5 API. */ @@ -252,8 +293,8 @@ policy_exists(const char *name) return TRUE; } -char * -kadmin_startup(int argc, char *argv[]) +void +kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out) { extern char *optarg; char *princstr = NULL, *keytab_name = NULL, *query = NULL; @@ -272,8 +313,7 @@ kadmin_startup(int argc, char *argv[]) memset(¶ms, 0, sizeof(params)); - if (strcmp(whoami, "kadmin.local") == 0) - set_com_err_hook(extended_com_err_fn); + set_com_err_hook(extended_com_err_fn); retval = kadm5_init_krb5_context(&context); if (retval) { @@ -282,15 +322,13 @@ kadmin_startup(int argc, char *argv[]) } while ((optchar = getopt(argc, argv, - "x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) { + "+x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) { switch (optchar) { case 'x': db_args_size++; db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); if (db_args == NULL) { - fprintf(stderr, - _("%s: Cannot initialize. Not enough memory\n"), - argv[0]); + error(_("%s: Cannot initialize. Not enough memory\n"), whoami); exit(1); } db_args[db_args_size - 1] = optarg; @@ -329,9 +367,7 @@ kadmin_startup(int argc, char *argv[]) db_args_size++; db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); if (db_args == NULL) { - fprintf(stderr, - _("%s: Cannot initialize. Not enough memory\n"), - argv[0]); + error(_("%s: Cannot initialize. Not enough memory\n"), whoami); exit(1); } db_args[db_args_size - 1] = db_name; @@ -372,8 +408,16 @@ kadmin_startup(int argc, char *argv[]) (use_anonymous && use_keytab)) usage(); + if (query != NULL && argv[optind] != NULL) { + error(_("%s: -q is exclusive with command-line query"), whoami); + usage(); + } + + if (argv[optind] != NULL) + script_mode = TRUE; + if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) { - fprintf(stderr, _("%s: unable to get default realm\n"), whoami); + error(_("%s: unable to get default realm\n"), whoami); exit(1); } @@ -421,7 +465,7 @@ kadmin_startup(int argc, char *argv[]) if (use_anonymous) { if (asprintf(&princstr, "%s/%s@%s", KRB5_WELLKNOWN_NAMESTR, KRB5_ANONYMOUS_PRINCSTR, def_realm) < 0) { - fprintf(stderr, _("%s: out of memory\n"), whoami); + error(_("%s: out of memory\n"), whoami); exit(1); } freeprinc++; @@ -452,8 +496,7 @@ kadmin_startup(int argc, char *argv[]) freeprinc++; } else if (!krb5_cc_get_principal(context, cc, &princ)) { if (krb5_unparse_name(context, princ, &canon)) { - fprintf(stderr, _("%s: unable to canonicalize principal\n"), - whoami); + error(_("%s: unable to canonicalize principal\n"), whoami); exit(1); } /* Strip out realm of principal if it's there. */ @@ -476,7 +519,7 @@ kadmin_startup(int argc, char *argv[]) if (asprintf(&princstr, "%s/admin%s%s", canon, (realm) ? "@" : "", (realm) ? realm : "") < 0) { - fprintf(stderr, _("%s: out of memory\n"), whoami); + error(_("%s: out of memory\n"), whoami); exit(1); } free(canon); @@ -484,20 +527,19 @@ kadmin_startup(int argc, char *argv[]) freeprinc++; } else if ((luser = getenv("USER"))) { if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) { - fprintf(stderr, _("%s: out of memory\n"), whoami); + error(_("%s: out of memory\n"), whoami); exit(1); } freeprinc++; } else if ((pw = getpwuid(getuid()))) { if (asprintf(&princstr, "%s/admin@%s", pw->pw_name, def_realm) < 0) { - fprintf(stderr, _("%s: out of memory\n"), whoami); + error(_("%s: out of memory\n"), whoami); exit(1); } freeprinc++; } else { - fprintf(stderr, _("%s: unable to figure out a principal name\n"), - whoami); + error(_("%s: unable to figure out a principal name\n"), whoami); exit(1); } } @@ -513,30 +555,31 @@ kadmin_startup(int argc, char *argv[]) * use it. Otherwise, use/prompt for the password. */ if (ccache_name) { - printf(_("Authenticating as principal %s with existing " - "credentials.\n"), princstr); + info(_("Authenticating as principal %s with existing " + "credentials.\n"), princstr); retval = kadm5_init_with_creds(context, princstr, cc, svcname, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, &handle); } else if (use_anonymous) { - printf(_("Authenticating as principal %s with password; " - "anonymous requested.\n"), princstr); + info(_("Authenticating as principal %s with password; " + "anonymous requested.\n"), princstr); retval = kadm5_init_anonymous(context, princstr, svcname, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, &handle); } else if (use_keytab) { - if (keytab_name) - printf(_("Authenticating as principal %s with keytab %s.\n"), - princstr, keytab_name); - else - printf(_("Authenticating as principal %s with default keytab.\n"), - princstr); + if (keytab_name != NULL) { + info(_("Authenticating as principal %s with keytab %s.\n"), + princstr, keytab_name); + } else { + info(_("Authenticating as principal %s with default keytab.\n"), + princstr); + } retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, &handle); } else { - printf(_("Authenticating as principal %s with password.\n"), - princstr); + info(_("Authenticating as principal %s with password.\n"), + princstr); retval = kadm5_init_with_password(context, princstr, password, svcname, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, @@ -567,7 +610,8 @@ kadmin_startup(int argc, char *argv[]) exit(1); } - return query; + *request_out = query; + *args_out = argv + optind; } int @@ -585,7 +629,7 @@ quit() } kadm5_destroy(handle); - if (ccache_name != NULL) { + if (ccache_name != NULL && !script_mode) { fprintf(stderr, "\n\a\a\a%s", _("Administration credentials NOT DESTROYED.\n")); } @@ -636,7 +680,7 @@ kadmin_delprinc(int argc, char *argv[]) if (! (argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) { - fprintf(stderr, _("usage: delete_principal [-force] principal\n")); + error(_("usage: delete_principal [-force] principal\n")); return; } retval = kadmin_parse_name(argv[argc - 1], &princ); @@ -650,7 +694,7 @@ kadmin_delprinc(int argc, char *argv[]) _("while canonicalizing principal")); goto cleanup; } - if (argc == 2) { + if (argc == 2 && !script_mode) { printf(_("Are you sure you want to delete the principal \"%s\"? " "(yes/no): "), canon); fgets(reply, sizeof (reply), stdin); @@ -665,9 +709,9 @@ kadmin_delprinc(int argc, char *argv[]) _("while deleting principal \"%s\""), canon); goto cleanup; } - printf(_("Principal \"%s\" deleted.\n"), canon); - printf(_("Make sure that you have removed this principal from all ACLs " - "before reusing.\n")); + info(_("Principal \"%s\" deleted.\n"), canon); + info(_("Make sure that you have removed this principal from all ACLs " + "before reusing.\n")); cleanup: krb5_free_principal(context, princ); @@ -683,8 +727,8 @@ kadmin_renameprinc(int argc, char *argv[]) char reply[5]; if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) { - fprintf(stderr, _("usage: rename_principal [-force] old_principal " - "new_principal\n")); + error(_("usage: rename_principal [-force] old_principal " + "new_principal\n")); return; } retval = kadmin_parse_name(argv[argc - 2], &oprinc); @@ -711,7 +755,7 @@ kadmin_renameprinc(int argc, char *argv[]) _("while canonicalizing new principal")); goto cleanup; } - if (argc == 3) { + if (argc == 3 && !script_mode) { printf(_("Are you sure you want to rename the principal \"%s\" " "to \"%s\"? (yes/no): "), ocanon, ncanon); fgets(reply, sizeof(reply), stdin); @@ -727,9 +771,9 @@ kadmin_renameprinc(int argc, char *argv[]) ocanon, ncanon); goto cleanup; } - printf(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon); - printf(_("Make sure that you have removed the old principal from all ACLs " - "before reusing.\n")); + info(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon); + info(_("Make sure that you have removed the old principal from all ACLs " + "before reusing.\n")); cleanup: krb5_free_principal(context, nprinc); @@ -742,9 +786,9 @@ static void cpw_usage(const char *str) { if (str) - fprintf(stderr, "%s\n", str); - fprintf(stderr, _("usage: change_password [-randkey] [-keepold] " - "[-e keysaltlist] [-pw password] principal\n")); + error("%s\n", str); + error(_("usage: change_password [-randkey] [-keepold] " + "[-e keysaltlist] [-pw password] principal\n")); } void @@ -775,7 +819,7 @@ kadmin_cpw(int argc, char *argv[]) db_args_size++; db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); if (db_args == NULL) { - fprintf(stderr, _("change_password: Not enough memory\n")); + error(_("change_password: Not enough memory\n")); exit(1); } db_args[db_args_size - 1] = *++argv; @@ -837,7 +881,7 @@ kadmin_cpw(int argc, char *argv[]) _("while changing password for \"%s\"."), canon); goto cleanup; } - printf(_("Password for \"%s\" changed.\n"), canon); + info(_("Password for \"%s\" changed.\n"), canon); } else if (randkey) { retval = randkey_princ(handle, princ, keepold, n_ks_tuple, ks_tuple, NULL, NULL); @@ -846,7 +890,7 @@ kadmin_cpw(int argc, char *argv[]) _("while randomizing key for \"%s\"."), canon); goto cleanup; } - printf(_("Key for \"%s\" randomized.\n"), canon); + info(_("Key for \"%s\" randomized.\n"), canon); } else { unsigned int i = sizeof (newpw) - 1; @@ -874,7 +918,7 @@ kadmin_cpw(int argc, char *argv[]) _("while changing password for \"%s\"."), canon); goto cleanup; } - printf(_("Password for \"%s\" changed.\n"), canon); + info(_("Password for \"%s\" changed.\n"), canon); } cleanup: free(canon); @@ -912,7 +956,7 @@ add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap, copy = malloc(len); tl_data = calloc(1, sizeof(*tl_data)); if (copy == NULL || tl_data == NULL) { - fprintf(stderr, _("Not enough memory\n")); + error(_("Not enough memory\n")); exit(1); } memcpy(copy, contents, len); @@ -991,8 +1035,7 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } oprinc->princ_expire_time = date; @@ -1004,8 +1047,7 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } oprinc->pw_expiration = date; @@ -1017,8 +1059,7 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } oprinc->max_life = date - now; @@ -1030,8 +1071,7 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } oprinc->max_renewable_life = date - now; @@ -1124,55 +1164,46 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, static void kadmin_addprinc_usage() { - fprintf(stderr, _("usage: add_principal [options] principal\n")); - fprintf(stderr, _("\toptions are:\n")); - fprintf(stderr, - _("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] " - "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" - "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" - "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" - "\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n") - ); - fprintf(stderr, _("\tattributes are:\n")); - fprintf(stderr, - _("\t\tallow_postdated allow_forwardable allow_tgs_req " - "allow_renewable\n" - "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" - "\t\trequires_hwauth needchange allow_svr " - "password_changing_service\n" - "\t\tok_as_delegate ok_to_auth_as_delegate " - "no_auth_data_required\n" - "\nwhere,\n\t[-x db_princ_args]* - any number of database " - "specific arguments.\n" - "\t\t\tLook at each database documentation for supported " - "arguments\n")); + error(_("usage: add_principal [options] principal\n")); + error(_("\toptions are:\n")); + error(_("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] " + "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" + "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" + "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" + "\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n")); + error(_("\tattributes are:\n")); + error(_("\t\tallow_postdated allow_forwardable allow_tgs_req " + "allow_renewable\n" + "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" + "\t\trequires_hwauth needchange allow_svr " + "password_changing_service\n" + "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" + "\nwhere,\n\t[-x db_princ_args]* - any number of database " + "specific arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n")); } static void kadmin_modprinc_usage() { - fprintf(stderr, _("usage: modify_principal [options] principal\n")); - fprintf(stderr, _("\toptions are:\n")); - fprintf(stderr, - _("\t\t[-x db_princ_args]* [-expire expdate] " - "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" - "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" - "\t\t[-maxrenewlife maxrenewlife] [-unlock] " - "[{+|-}attribute]\n")); - fprintf(stderr, "\tattributes are:\n"); - fprintf(stderr, - _("\t\tallow_postdated allow_forwardable allow_tgs_req " - "allow_renewable\n" - "\t\tallow_proxiable allow_dup_skey allow_tix " - "requires_preauth\n" - "\t\trequires_hwauth needchange allow_svr " - "password_changing_service\n" - "\t\tok_as_delegate ok_to_auth_as_delegate " - "no_auth_data_required\n" - "\nwhere,\n\t[-x db_princ_args]* - any number of database " - "specific arguments.\n" - "\t\t\tLook at each database documentation for supported " - "arguments\n")); + error(_("usage: modify_principal [options] principal\n")); + error(_("\toptions are:\n")); + error(_("\t\t[-x db_princ_args]* [-expire expdate] " + "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" + "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" + "\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n")); + error(_("\tattributes are:\n")); + error(_("\t\tallow_postdated allow_forwardable allow_tgs_req " + "allow_renewable\n" + "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" + "\t\trequires_hwauth needchange allow_svr " + "password_changing_service\n" + "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" + "\nwhere,\n\t[-x db_princ_args]* - any number of database " + "specific arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n")); } /* Create a dummy password for old-style (pre-1.8) randkey creation. */ @@ -1220,20 +1251,23 @@ kadmin_addprinc(int argc, char *argv[]) if (mask & KADM5_POLICY) { /* Warn if the specified policy does not exist. */ - if (!policy_exists(princ.policy)) { + if (!script_mode && !policy_exists(princ.policy)) { fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"), princ.policy); } } else if (!(mask & KADM5_POLICY_CLR)) { /* If the policy "default" exists, assign it. */ if (policy_exists("default")) { - fprintf(stderr, _("NOTICE: no policy specified for %s; " - "assigning \"default\"\n"), canon); + if (!script_mode) { + fprintf(stderr, _("NOTICE: no policy specified for %s; " + "assigning \"default\"\n"), canon); + } princ.policy = "default"; mask |= KADM5_POLICY; - } else + } else if (!script_mode) { fprintf(stderr, _("WARNING: no policy specified for %s; " "defaulting to no policy\n"), canon); + } } /* Don't send KADM5_POLICY_CLR to the server. */ mask &= ~KADM5_POLICY_CLR; @@ -1273,8 +1307,8 @@ kadmin_addprinc(int argc, char *argv[]) old_style_randkey = 1; } if (retval == KADM5_BAD_MASK && nokey) { - fprintf(stderr, _("Admin server does not support -nokey while " - "creating \"%s\"\n"), canon); + error(_("Admin server does not support -nokey while creating " + "\"%s\"\n"), canon); goto cleanup; } if (retval) { @@ -1299,7 +1333,7 @@ kadmin_addprinc(int argc, char *argv[]) goto cleanup; } } - printf("Principal \"%s\" created.\n", canon); + info("Principal \"%s\" created.\n", canon); cleanup: krb5_free_principal(context, princ.principal); @@ -1358,7 +1392,7 @@ kadmin_modprinc(int argc, char *argv[]) } if (mask & KADM5_POLICY) { /* Warn if the specified policy does not exist. */ - if (!policy_exists(princ.policy)) { + if (!script_mode && !policy_exists(princ.policy)) { fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"), princ.policy); } @@ -1372,7 +1406,7 @@ kadmin_modprinc(int argc, char *argv[]) canon); goto cleanup; } - printf(_("Principal \"%s\" modified.\n"), canon); + info(_("Principal \"%s\" modified.\n"), canon); cleanup: krb5_free_principal(context, kprinc); krb5_free_principal(context, princ.principal); @@ -1393,7 +1427,7 @@ kadmin_getprinc(int argc, char *argv[]) size_t j; if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) { - fprintf(stderr, _("usage: get_principal [-terse] principal\n")); + error(_("usage: get_principal [-terse] principal\n")); return; } @@ -1514,7 +1548,7 @@ kadmin_getprincs(int argc, char *argv[]) expr = NULL; if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) { - fprintf(stderr, _("usage: get_principals [expression]\n")); + error(_("usage: get_principals [expression]\n")); return; } retval = kadm5_get_principals(handle, expr, &names, &count); @@ -1543,8 +1577,7 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } policy->pw_max_life = date - now; @@ -1555,8 +1588,7 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, return -1; date = get_date(argv[i]); if (date == (time_t)-1) { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } policy->pw_min_life = date - now; @@ -1598,8 +1630,7 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, else if (isdigit(*argv[i])) policy->pw_failcnt_interval = atoi(argv[i]); else { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } *mask |= KADM5_PW_FAILURE_COUNT_INTERVAL; @@ -1615,8 +1646,7 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, else if (isdigit(*argv[i])) policy->pw_lockout_duration = atoi(argv[i]); else { - fprintf(stderr, _("Invalid date specification \"%s\".\n"), - argv[i]); + error(_("Invalid date specification \"%s\".\n"), argv[i]); return -1; } *mask |= KADM5_PW_LOCKOUT_DURATION; @@ -1644,7 +1674,7 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, return -1; } if (i != argc -1) { - fprintf(stderr, _("%s: parser lost count!\n"), caller); + error(_("%s: parser lost count!\n"), caller); return -1; } else return 0; @@ -1653,14 +1683,13 @@ kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, static void kadmin_addmodpol_usage(char *func) { - fprintf(stderr, _("usage; %s [options] policy\n"), func); - fprintf(stderr, _("\toptions are:\n")); - fprintf(stderr, - _("\t\t[-maxlife time] [-minlife time] [-minlength length]\n" - "\t\t[-minclasses number] [-history number]\n" - "\t\t[-maxfailure number] [-failurecountinterval time]\n" - "\t\t[-allowedkeysalts keysalts]\n")); - fprintf(stderr, _("\t\t[-lockoutduration time]\n")); + error(_("usage; %s [options] policy\n"), func); + error(_("\toptions are:\n")); + error(_("\t\t[-maxlife time] [-minlife time] [-minlength length]\n" + "\t\t[-minclasses number] [-history number]\n" + "\t\t[-maxfailure number] [-failurecountinterval time]\n" + "\t\t[-allowedkeysalts keysalts]\n")); + error(_("\t\t[-lockoutduration time]\n")); } void @@ -1712,10 +1741,10 @@ kadmin_delpol(int argc, char *argv[]) char reply[5]; if (!(argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) { - fprintf(stderr, _("usage: delete_policy [-force] policy\n")); + error(_("usage: delete_policy [-force] policy\n")); return; } - if (argc == 2) { + if (argc == 2 && !script_mode) { printf(_("Are you sure you want to delete the policy \"%s\"? " "(yes/no): "), argv[1]); fgets(reply, sizeof(reply), stdin); @@ -1738,7 +1767,7 @@ kadmin_getpol(int argc, char *argv[]) kadm5_policy_ent_rec policy; if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) { - fprintf(stderr, _("usage: get_policy [-terse] policy\n")); + error(_("usage: get_policy [-terse] policy\n")); return; } retval = kadm5_get_policy(handle, argv[argc - 1], &policy); @@ -1786,7 +1815,7 @@ kadmin_getpols(int argc, char *argv[]) expr = NULL; if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) { - fprintf(stderr, _("usage: get_policies [expression]\n")); + error(_("usage: get_policies [expression]\n")); return; } retval = kadm5_get_policies(handle, expr, &names, &count); @@ -1808,7 +1837,7 @@ kadmin_getprivs(int argc, char *argv[]) long plist; if (argc != 1) { - fprintf(stderr, _("usage: get_privs\n")); + error(_("usage: get_privs\n")); return; } retval = kadm5_get_privs(handle, &plist); @@ -1842,8 +1871,8 @@ kadmin_purgekeys(int argc, char *argv[]) pname = argv[1]; } if (pname == NULL) { - fprintf(stderr, _("usage: purgekeys " - "[-all|-keepkvno oldest_kvno_to_keep] principal\n")); + error(_("usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] " + "principal\n")); return; } @@ -1867,9 +1896,9 @@ kadmin_purgekeys(int argc, char *argv[]) } if (keepkvno == KRB5_INT32_MAX) - printf(_("All keys for principal \"%s\" removed.\n"), canon); + info(_("All keys for principal \"%s\" removed.\n"), canon); else - printf(_("Old keys for principal \"%s\" purged.\n"), canon); + info(_("Old keys for principal \"%s\" purged.\n"), canon); cleanup: krb5_free_principal(context, princ); free(canon); @@ -1886,7 +1915,7 @@ kadmin_getstrings(int argc, char *argv[]) int count, i; if (argc != 2) { - fprintf(stderr, _("usage: get_strings principal\n")); + error(_("usage: get_strings principal\n")); return; } pname = argv[1]; @@ -1930,7 +1959,7 @@ kadmin_setstring(int argc, char *argv[]) krb5_principal princ = NULL; if (argc != 4) { - fprintf(stderr, _("usage: set_string principal key value\n")); + error(_("usage: set_string principal key value\n")); return; } pname = argv[1]; @@ -1956,7 +1985,7 @@ kadmin_setstring(int argc, char *argv[]) goto cleanup; } - printf(_("Attribute set for principal \"%s\".\n"), canon); + info(_("Attribute set for principal \"%s\".\n"), canon); cleanup: krb5_free_principal(context, princ); free(canon); @@ -1971,7 +2000,7 @@ kadmin_delstring(int argc, char *argv[]) krb5_principal princ = NULL; if (argc != 3) { - fprintf(stderr, _("usage: del_string principal key\n")); + error(_("usage: del_string principal key\n")); return; } pname = argv[1]; @@ -1996,7 +2025,7 @@ kadmin_delstring(int argc, char *argv[]) goto cleanup; } - printf(_("Attribute removed from principal \"%s\".\n"), canon); + info(_("Attribute removed from principal \"%s\".\n"), canon); cleanup: krb5_free_principal(context, princ); free(canon); diff --git a/src/kadmin/cli/kadmin.h b/src/kadmin/cli/kadmin.h index 9cff390b86..72bda938b1 100644 --- a/src/kadmin/cli/kadmin.h +++ b/src/kadmin/cli/kadmin.h @@ -33,7 +33,8 @@ #define __KADMIN_H__ /* It would be nice if ss produced a header file we could reference */ -extern char *kadmin_startup(int argc, char *argv[]); +extern void kadmin_startup(int argc, char *argv[], char **request_out, + char ***args_out); extern int quit (void); extern void kadmin_lock(int argc, char *argv[]); extern void kadmin_unlock(int argc, char *argv[]); diff --git a/src/kadmin/cli/ss_wrapper.c b/src/kadmin/cli/ss_wrapper.c index bd368a8066..d9a1d8f77e 100644 --- a/src/kadmin/cli/ss_wrapper.c +++ b/src/kadmin/cli/ss_wrapper.c @@ -36,26 +36,30 @@ extern char *whoami; int main(int argc, char *argv[]) { - char *request; + char *request, **args; krb5_error_code retval; int sci_idx, code = 0; setlocale(LC_ALL, ""); whoami = ((whoami = strrchr(argv[0], '/')) ? whoami+1 : argv[0]); - request = kadmin_startup(argc, argv); + kadmin_startup(argc, argv, &request, &args); sci_idx = ss_create_invocation(whoami, "5.0", NULL, &kadmin_cmds, &retval); if (retval) { ss_perror(sci_idx, retval, _("creating invocation")); exit(1); } - if (request) { - code = ss_execute_line(sci_idx, request); + if (request == NULL && *args == NULL) { + (void)ss_listen(sci_idx); + } else { + if (request != NULL) + code = ss_execute_line(sci_idx, request); + else + code = ss_execute_command(sci_idx, args); if (code != 0) { ss_perror(sci_idx, code, request); - exit_status++; + exit_status = 1; } - } else - retval = ss_listen(sci_idx); + } return quit() ? 1 : exit_status; }