From 779a335f4e2deb2d76caf7d0dd3de847a040c050 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 26 Jan 2014 16:42:50 -0500 Subject: Clean up ovsec_kadmd.c Fix code formatting issues. Use static scope when possible, and put all helper functions before main so that forward declarations aren't needed. Use GSS_KRB5_NT_PRINCIPAL_NAME instead of constructing it with gss_str_to_oid, and get rid of display_status as that was the only use. Replace large verbose function comments with concise ones. Factor out main loop setup and KDB keytab setup into helper functions. Create a helper function fail_to_start for logging and exiting on initialization failures, and use it instead of the large cleanup blocks in main. Some initialization error messages have changed; no other functional changes. --- src/kadmin/server/ovsec_kadmd.c | 1059 +++++++++++++-------------------------- 1 file changed, 342 insertions(+), 717 deletions(-) diff --git a/src/kadmin/server/ovsec_kadmd.c b/src/kadmin/server/ovsec_kadmd.c index 87aa47a804..61efa507b4 100644 --- a/src/kadmin/server/ovsec_kadmd.c +++ b/src/kadmin/server/ovsec_kadmd.c @@ -30,79 +30,57 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #ifdef _AIX -#include +#include #endif -#include -#include -#include -#include -#include -#include -#include -#include "gssapiP_krb5.h" /* for kg_get_context */ -#include -#include -#include -#include -#include -#include "kdb_kt.h" /* for krb5_ktkdb_set_context */ -#include -#include "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */ -#include - -#include "misc.h" +#include +#include +#include +#include +#include +#include +#include +#include "gssapiP_krb5.h" /* for kg_get_context */ +#include +#include +#include +#include +#include +#include "kdb_kt.h" /* for krb5_ktkdb_set_context */ +#include +#include "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */ +#include + +#include "misc.h" #if defined(NEED_DAEMON_PROTO) -extern int daemon(int, int); +int daemon(int, int); #endif #define TIMEOUT 15 gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL; -gss_name_t gss_kadmin_name = NULL; void *global_server_handle; +int nofork = 0; +char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL; +char *kprop = KPROPD_DEFAULT_KPROP; +char *dump_file = KPROP_DEFAULT_FILE; -char *build_princ_name(char *name, char *realm); -void log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data); -void log_badverf(gss_name_t client_name, gss_name_t server_name, - struct svc_req *rqst, struct rpc_msg *msg, - char *data); -void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char - *error, char *data); -void log_badauth_display_status(char *msg, OM_uint32 major, OM_uint32 minor); -void log_badauth_display_status_1(char *m, OM_uint32 code, int type, - int rec); - -int schpw; -void do_schpw(int s, kadm5_config_params *params); - -#ifndef DISABLE_IPROP -int ipropfd; -#endif +static krb5_context context; +static char *progname; #ifdef USE_PASSWORD_SERVER -void kadm5_set_use_password_server (void); +void kadm5_set_use_password_server(void); #endif -/* - * Function: usage - * - * Purpose: print out the server usage message - * - * Arguments: - * Requires: - * Effects: - * Modifies: - */ - -static void usage() +static void +usage() { fprintf(stderr, _("Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] " "[-port port-number]\n" @@ -116,70 +94,29 @@ static void usage() } /* - * Function: display_status - * - * Purpose: displays GSS-API messages - * - * Arguments: - * - * msg a string to be displayed with the message - * maj_stat the GSS-API major status code - * min_stat the GSS-API minor status code - * - * Effects: - * - * The GSS-API messages associated with maj_stat and min_stat are - * displayed on stderr, each preceeded by "GSS-API error : " and - * followed by a newline. + * Output a message to stderr and the admin server log, and exit with status 1. + * msg should not be punctuated. If code is given, msg should indicate what + * operation was taking place in the present progressive. Otherwise msg should + * be capitalized and should indicate what went wrong. */ -static void display_status_1(char *, OM_uint32, int); - -static void display_status(msg, maj_stat, min_stat) - char *msg; - OM_uint32 maj_stat; - OM_uint32 min_stat; -{ - display_status_1(msg, maj_stat, GSS_C_GSS_CODE); - display_status_1(msg, min_stat, GSS_C_MECH_CODE); -} - -static void display_status_1(m, code, type) - char *m; - OM_uint32 code; - int type; +static void +fail_to_start(krb5_error_code code, const char *msg) { - OM_uint32 min_stat; - gss_buffer_desc msg; - OM_uint32 msg_ctx; - - msg_ctx = 0; - while (1) { - (void) gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, - &msg_ctx, &msg); - fprintf(stderr, _("GSS-API error %s: %s\n"), m, (char *)msg.value); - (void) gss_release_buffer(&min_stat, &msg); + const char *errmsg; - if (!msg_ctx) - break; + fprintf(stderr, "%s: ", progname); + if (code) { + errmsg = krb5_get_error_message(context, code); + fprintf(stderr, _("%s: %s while %s, aborting\n"), progname, errmsg, + msg); + krb5_klog_syslog(LOG_ERR, _("%s while %s, aborting\n"), errmsg, msg); + } else { + fprintf(stderr, _("%s: %s, aborting\n"), progname, msg); + krb5_klog_syslog(LOG_ERR, _("%s, aborting"), msg); } + exit(1); } -/* - * Function: write_pid_file - * - * Purpose: writes the current process PID to a file - * - * Arguments: - * - * pid_file path to output file - * 0 on success, error code on failure - * - * Effects: - * - * The current process PID, obtained from getpid(), is written to the path - * given in pid_file, overwriting the existing contents if the file already - * exists. The PID will be followed by a newline. - */ static int write_pid_file(const char *pid_file) { @@ -190,92 +127,264 @@ write_pid_file(const char *pid_file) file = fopen(pid_file, "w"); if (file == NULL) return errno; - pid = (unsigned long) getpid(); + pid = (unsigned long)getpid(); st1 = (fprintf(file, "%ld\n", pid) < 0) ? errno : 0; st2 = (fclose(file) == EOF) ? errno : 0; return st1 ? st1 : st2; } -/* XXX yuck. the signal handlers need this */ -static krb5_context context; +/* Set up the main loop. May set *ctx_out even on error. */ +static krb5_error_code +setup_loop(verto_ctx **ctx_out) +{ + krb5_error_code ret; + verto_ctx *ctx; + kadm5_server_handle_t handle = global_server_handle; + + *ctx_out = ctx = loop_init(VERTO_EV_TYPE_SIGNAL); + if (ctx == NULL) + return ENOMEM; + ret = loop_setup_signals(ctx, global_server_handle, NULL); + if (ret) + return ret; + ret = loop_add_udp_port(handle->params.kpasswd_port); + if (ret) + return ret; + ret = loop_add_tcp_port(handle->params.kpasswd_port); + if (ret) + return ret; + ret = loop_add_rpc_service(handle->params.kadmind_port, KADM, KADMVERS, + kadm_1); + if (ret) + return ret; +#ifndef DISABLE_IPROP + if (handle->params.iprop_enabled) { + ret = loop_add_rpc_service(handle->params.iprop_port, KRB5_IPROP_PROG, + KRB5_IPROP_VERS, krb5_iprop_prog_1); + if (ret) + return ret; + } +#endif + ret = loop_setup_routing_socket(ctx, global_server_handle, progname); + if (ret) + return ret; + return loop_setup_network(ctx, global_server_handle, progname); +} -static krb5_context hctx; +/* Point GSSAPI at the KDB keytab so we don't need an actual file keytab. */ +static krb5_error_code +setup_kdb_keytab() +{ + krb5_error_code ret; + + ret = krb5_ktkdb_set_context(context); + if (ret) + return ret; + ret = krb5_kt_register(context, &krb5_kt_kdb_ops); + if (ret) + return ret; + return krb5_gss_register_acceptor_identity("KDB:"); +} -int nofork = 0; -char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL; -char *kprop = KPROPD_DEFAULT_KPROP; -char *dump_file = KPROP_DEFAULT_FILE; -int main(int argc, char *argv[]) +/* Return "name@realm". */ +static char * +build_princ_name(char *name, char *realm) { - int ret; - OM_uint32 OMret, major_status, minor_status; - char *whoami; + char *fullname; + + if (asprintf(&fullname, "%s@%s", name, realm) < 0) + return NULL; + return fullname; +} + +/* Callback from GSSRPC for garbled/forged/replayed/etc messages. */ +static void +log_badverf(gss_name_t client_name, gss_name_t server_name, + struct svc_req *rqst, struct rpc_msg *msg, char *data) +{ + static const struct { + rpcproc_t proc; + const char *proc_name; + } proc_names[] = { + {1, "CREATE_PRINCIPAL"}, + {2, "DELETE_PRINCIPAL"}, + {3, "MODIFY_PRINCIPAL"}, + {4, "RENAME_PRINCIPAL"}, + {5, "GET_PRINCIPAL"}, + {6, "CHPASS_PRINCIPAL"}, + {7, "CHRAND_PRINCIPAL"}, + {8, "CREATE_POLICY"}, + {9, "DELETE_POLICY"}, + {10, "MODIFY_POLICY"}, + {11, "GET_POLICY"}, + {12, "GET_PRIVS"}, + {13, "INIT"}, + {14, "GET_PRINCS"}, + {15, "GET_POLS"}, + {16, "SETKEY_PRINCIPAL"}, + {17, "SETV4KEY_PRINCIPAL"}, + {18, "CREATE_PRINCIPAL3"}, + {19, "CHPASS_PRINCIPAL3"}, + {20, "CHRAND_PRINCIPAL3"}, + {21, "SETKEY_PRINCIPAL3"}, + {22, "PURGEKEYS"}, + {23, "GET_STRINGS"}, + {24, "SET_STRING"} + }; + OM_uint32 minor; + gss_buffer_desc client, server; + gss_OID gss_type; + const char *a; + rpcproc_t proc; + unsigned int i; + const char *procname; + size_t clen, slen; + char *cdots, *sdots; + + client.length = 0; + client.value = NULL; + server.length = 0; + server.value = NULL; + + (void)gss_display_name(&minor, client_name, &client, &gss_type); + (void)gss_display_name(&minor, server_name, &server, &gss_type); + if (client.value == NULL) { + client.value = "(null)"; + clen = sizeof("(null)") - 1; + } else { + clen = client.length; + } + trunc_name(&clen, &cdots); + if (server.value == NULL) { + server.value = "(null)"; + slen = sizeof("(null)") - 1; + } else { + slen = server.length; + } + trunc_name(&slen, &sdots); + a = client_addr(rqst->rq_xprt); + + proc = msg->rm_call.cb_proc; + procname = NULL; + for (i = 0; i < sizeof(proc_names) / sizeof(*proc_names); i++) { + if (proc_names[i].proc == proc) { + procname = proc_names[i].proc_name; + break; + } + } + if (procname != NULL) { + krb5_klog_syslog(LOG_NOTICE, + _("WARNING! Forged/garbled request: %s, claimed " + "client = %.*s%s, server = %.*s%s, addr = %s"), + procname, (int)clen, (char *)client.value, cdots, + (int)slen, (char *)server.value, sdots, a); + } else { + krb5_klog_syslog(LOG_NOTICE, + _("WARNING! Forged/garbled request: %d, claimed " + "client = %.*s%s, server = %.*s%s, addr = %s"), + proc, (int)clen, (char *)client.value, cdots, + (int)slen, (char *)server.value, sdots, a); + } + + (void)gss_release_buffer(&minor, &client); + (void)gss_release_buffer(&minor, &server); +} + +/* Callback from GSSRPC for miscellaneous errors */ +static void +log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char *error, char *data) +{ + krb5_klog_syslog(LOG_NOTICE, _("Miscellaneous RPC error: %s, %s"), + client_addr(rqst->rq_xprt), error); +} + +static void +log_badauth_display_status_1(char *m, OM_uint32 code, int type) +{ + OM_uint32 gssstat, minor_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + gssstat = gss_display_status(&minor_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (gssstat != GSS_S_COMPLETE) { + krb5_klog_syslog(LOG_ERR, _("%s Cannot decode status %d"), m, + (int)code); + return; + } + + krb5_klog_syslog(LOG_NOTICE, "%s %.*s", m, (int)msg.length, + (char *)msg.value); + (void)gss_release_buffer(&minor_stat, &msg); + + if (!msg_ctx) + break; + } +} + +/* Callback from GSSRPC for authentication failures */ +void +log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data) +{ + krb5_klog_syslog(LOG_NOTICE, _("Authentication attempt failed: %s, " + "GSS-API error strings are:"), + client_addr(xprt)); + log_badauth_display_status_1(" ", major, GSS_C_GSS_CODE); + log_badauth_display_status_1(" ", minor, GSS_C_MECH_CODE); + krb5_klog_syslog(LOG_NOTICE, _(" GSS-API error strings complete.")); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor_status; gss_buffer_desc in_buf; + gss_OID nt_krb5_name_oid = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME; auth_gssapi_name names[4]; - gss_buffer_desc gssbuf; - gss_OID nt_krb5_name_oid; kadm5_config_params params; - char **db_args = NULL; - int db_args_size = 0; - const char *errmsg; - int i; - int strong_random = 1; + verto_ctx *vctx; const char *pid_file = NULL; - - kdb_log_context *log_ctx; - - verto_ctx *ctx; + char **db_args = NULL, **tmpargs; + int ret, i, db_args_size = 0, strong_random = 1; setlocale(LC_ALL, ""); setvbuf(stderr, NULL, _IONBF, 0); - /* This is OID value the Krb5_Name NameType */ - gssbuf.value = "{1 2 840 113554 1 2 2 1}"; - gssbuf.length = strlen(gssbuf.value); - major_status = gss_str_to_oid(&minor_status, &gssbuf, &nt_krb5_name_oid); - if (major_status != GSS_S_COMPLETE) { - fprintf(stderr, _("Couldn't create KRB5 Name NameType OID\n")); - display_status("str_to_oid", major_status, minor_status); - exit(1); - } - names[0].name = names[1].name = names[2].name = names[3].name = NULL; names[0].type = names[1].type = names[2].type = names[3].type = nt_krb5_name_oid; - whoami = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]); - - nofork = 0; + progname = (strrchr(argv[0], '/') != NULL) ? strrchr(argv[0], '/') + 1 : + argv[0]; memset(¶ms, 0, sizeof(params)); - argc--; argv++; + argc--, argv++; while (argc) { if (strcmp(*argv, "-x") == 0) { - argc--; argv++; + argc--, argv++; if (!argc) usage(); db_args_size++; - { - char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ - if( temp == NULL ) - { - fprintf(stderr, _("%s: cannot initialize. Not enough " - "memory\n"), whoami); - exit(1); - } - db_args = temp; + tmpargs = realloc(db_args, sizeof(char *) * (db_args_size + 1)); + if (tmpargs == NULL) { + fprintf(stderr, _("%s: cannot initialize. Not enough " + "memory\n"), progname); + exit(1); } - db_args[db_args_size-1] = *argv; - db_args[db_args_size] = NULL; - }else if (strcmp(*argv, "-r") == 0) { - argc--; argv++; + db_args = tmpargs; + db_args[db_args_size - 1] = *argv; + db_args[db_args_size] = NULL; + } else if (strcmp(*argv, "-r") == 0) { + argc--, argv++; if (!argc) usage(); params.realm = *argv; params.mask |= KADM5_CONFIG_REALM; - argc--; argv++; + argc--, argv++; continue; } else if (strcmp(*argv, "-m") == 0) { params.mkey_from_kbd = 1; @@ -284,208 +393,89 @@ int main(int argc, char *argv[]) nofork = 1; #ifdef USE_PASSWORD_SERVER } else if (strcmp(*argv, "-passwordserver") == 0) { - kadm5_set_use_password_server (); + kadm5_set_use_password_server(); #endif - } else if(strcmp(*argv, "-port") == 0) { - argc--; argv++; - if(!argc) + } else if (strcmp(*argv, "-port") == 0) { + argc--, argv++; + if (!argc) usage(); params.kadmind_port = atoi(*argv); params.mask |= KADM5_CONFIG_KADMIND_PORT; } else if (strcmp(*argv, "-P") == 0) { - argc--; argv++; + argc--, argv++; if (!argc) usage(); pid_file = *argv; } else if (strcmp(*argv, "-W") == 0) { strong_random = 0; } else if (strcmp(*argv, "-p") == 0) { - argc--; argv++; + argc--, argv++; if (!argc) usage(); kdb5_util = *argv; } else if (strcmp(*argv, "-F") == 0) { - argc--; argv++; + argc--, argv++; if (!argc) usage(); dump_file = *argv; } else if (strcmp(*argv, "-K") == 0) { - argc--; argv++; + argc--, argv++; if (!argc) usage(); kprop = *argv; - } else + } else { break; - argc--; argv++; + } + argc--, argv++; } if (argc != 0) usage(); - if ((ret = kadm5_init_krb5_context(&context))) { + ret = kadm5_init_krb5_context(&context); + if (ret) { fprintf(stderr, _("%s: %s while initializing context, aborting\n"), - whoami, error_message(ret)); - exit(1); - } - - krb5_klog_init(context, "admin_server", whoami, 1); - - if((ret = kadm5_init(context, "kadmind", NULL, - NULL, ¶ms, - KADM5_STRUCT_VERSION, - KADM5_API_VERSION_4, - db_args, - &global_server_handle)) != KADM5_OK) { - const char *e_txt = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("%s while initializing, aborting"), e_txt); - fprintf(stderr, _("%s: %s while initializing, aborting\n"), - whoami, e_txt); - krb5_klog_close(context); + progname, error_message(ret)); exit(1); } - if ((ret = kadm5_get_config_params(context, 1, ¶ms, - ¶ms))) { - const char *e_txt = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("%s: %s while initializing, aborting"), - whoami, e_txt); - fprintf(stderr, _("%s: %s while initializing, aborting\n"), - whoami, e_txt); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + krb5_klog_init(context, "admin_server", progname, 1); -#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_ACL_FILE) - - if ((params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { - krb5_klog_syslog(LOG_ERR, - _("%s: Missing required configuration values " - "(%lx) while initializing, aborting"), whoami, - (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS); - fprintf(stderr, _("%s: Missing required configuration values " - "(%lx) while initializing, aborting\n"), whoami, - (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS); - krb5_klog_close(context); - kadm5_destroy(global_server_handle); - exit(1); - } + ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, + &global_server_handle); + if (ret) + fail_to_start(ret, _("initializing")); - ctx = loop_init(VERTO_EV_TYPE_SIGNAL); - if (!ctx) { - krb5_klog_syslog(LOG_ERR, - _("%s: could not initialize loop, aborting"), - whoami); - fprintf(stderr, _("%s: could not initialize loop, aborting\n"), - whoami); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + ret = kadm5_get_config_params(context, 1, ¶ms, ¶ms); + if (ret) + fail_to_start(ret, _("getting config parameters")); + if (!(params.mask & KADM5_CONFIG_REALM)) + fail_to_start(0, _("Missing required realm configuration")); + if (!(params.mask & KADM5_CONFIG_ACL_FILE)) + fail_to_start(0, _("Missing required ACL file configuration")); - if ((ret = loop_setup_signals(ctx, global_server_handle, NULL))) { - const char *e_txt = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("%s: %s while initializing signal " - "handlers, aborting"), whoami, e_txt); - fprintf(stderr, _("%s: %s while initializing signal " - "handlers, aborting\n"), whoami, e_txt); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } - -#define server_handle ((kadm5_server_handle_t)global_server_handle) - if ((ret = loop_add_udp_port(server_handle->params.kpasswd_port)) - || (ret = loop_add_tcp_port(server_handle->params.kpasswd_port)) - || (ret = loop_add_rpc_service(server_handle->params.kadmind_port, - KADM, KADMVERS, kadm_1)) -#ifndef DISABLE_IPROP - || (server_handle->params.iprop_enabled - ? (ret = loop_add_rpc_service(server_handle->params.iprop_port, - KRB5_IPROP_PROG, KRB5_IPROP_VERS, - krb5_iprop_prog_1)) - : 0) -#endif -#undef server_handle - || (ret = loop_setup_routing_socket(ctx, global_server_handle, whoami)) - || (ret = loop_setup_network(ctx, global_server_handle, whoami))) { - const char *e_txt = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("%s: %s while initializing network, " - "aborting"), whoami, e_txt); - fprintf(stderr, _("%s: %s while initializing network, aborting\n"), - whoami, e_txt); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + ret = setup_loop(&vctx); + if (ret) + fail_to_start(ret, _("initializing network")); names[0].name = build_princ_name(KADM5_ADMIN_SERVICE, params.realm); names[1].name = build_princ_name(KADM5_CHANGEPW_SERVICE, params.realm); - if (names[0].name == NULL || names[1].name == NULL) { - krb5_klog_syslog(LOG_ERR, _("Cannot build GSS-API authentication " - "names, failing.")); - fprintf(stderr, _("%s: Cannot build GSS-API authentication names.\n"), - whoami); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + if (names[0].name == NULL || names[1].name == NULL) + fail_to_start(0, _("Cannot build GSSAPI auth names")); - /* - * Go through some contortions to point gssapi at a kdb keytab. - * This prevents kadmind from needing to use an actual file-based - * keytab. - */ - /* XXX extract kadm5's krb5_context */ - hctx = ((kadm5_server_handle_t)global_server_handle)->context; - /* Set ktkdb's internal krb5_context. */ - ret = krb5_ktkdb_set_context(hctx); - if (ret) { - krb5_klog_syslog(LOG_ERR, - _("Can't set kdb keytab's internal context.")); - goto kterr; - } - ret = krb5_kt_register(context, &krb5_kt_kdb_ops); - if (ret) { - krb5_klog_syslog(LOG_ERR, _("Can't register kdb keytab.")); - goto kterr; - } - /* Tell gssapi about the kdb keytab. */ - ret = krb5_gss_register_acceptor_identity("KDB:"); - if (ret) { - krb5_klog_syslog(LOG_ERR, _("Can't register acceptor keytab.")); - goto kterr; - } -kterr: - if (ret) { - krb5_klog_syslog(LOG_ERR, "%s", krb5_get_error_message (context, ret)); - fprintf(stderr, _("%s: Can't set up keytab for RPC.\n"), whoami); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + ret = setup_kdb_keytab(); + if (ret) + fail_to_start(0, _("Cannot set up KDB keytab")); - if (svcauth_gssapi_set_names(names, 2) == FALSE) { - krb5_klog_syslog(LOG_ERR, _("Cannot set GSS-API authentication names " - "(keytab not present?), failing.")); - fprintf(stderr, _("%s: Cannot set GSS-API authentication names.\n"), - whoami); - svcauth_gssapi_unset_names(); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + if (svcauth_gssapi_set_names(names, 2) == FALSE) + fail_to_start(0, _("Cannot set GSSAPI authentication names")); /* if set_names succeeded, this will too */ in_buf.value = names[1].name; in_buf.length = strlen(names[1].name) + 1; - (void) gss_import_name(&OMret, &in_buf, nt_krb5_name_oid, - &gss_changepw_name); + (void)gss_import_name(&minor_status, &in_buf, nt_krb5_name_oid, + &gss_changepw_name); svcauth_gssapi_set_log_badauth2_func(log_badauth, NULL); svcauth_gssapi_set_log_badverf_func(log_badverf, NULL); @@ -495,424 +485,59 @@ kterr: svcauth_gss_set_log_badverf_func(log_badverf, NULL); svcauth_gss_set_log_miscerr_func(log_miscerr, NULL); - if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) { - fprintf(stderr, _("%s: Cannot initialize RPCSEC_GSS service name.\n"), - whoami); - loop_free(ctx); - exit(1); - } + if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) + fail_to_start(0, _("Cannot initialize GSSAPI service name")); - if ((ret = kadm5int_acl_init(context, 0, params.acl_file))) { - errmsg = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("Cannot initialize acl file: %s"), errmsg); - fprintf(stderr, _("%s: Cannot initialize acl file: %s\n"), - whoami, errmsg); - svcauth_gssapi_unset_names(); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + ret = kadm5int_acl_init(context, 0, params.acl_file); + if (ret) + fail_to_start(ret, _("initializing ACL file")); - if (!nofork && (ret = daemon(0, 0))) { - ret = errno; - errmsg = krb5_get_error_message (context, ret); - krb5_klog_syslog(LOG_ERR, _("Cannot detach from tty: %s"), errmsg); - fprintf(stderr, _("%s: Cannot detach from tty: %s\n"), whoami, errmsg); - svcauth_gssapi_unset_names(); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + if (!nofork && daemon(0, 0) != 0) + fail_to_start(errno, _("spawning daemon process")); if (pid_file != NULL) { ret = write_pid_file(pid_file); - if (ret) { - errmsg = krb5_get_error_message(context, ret); - krb5_klog_syslog(LOG_ERR, _("Cannot create PID file %s: %s"), - pid_file, errmsg); - svcauth_gssapi_unset_names(); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + if (ret) + fail_to_start(ret, _("creating PID file")); } krb5_klog_syslog(LOG_INFO, _("Seeding random number generator")); ret = krb5_c_random_os_entropy(context, strong_random, NULL); - if (ret) { - krb5_klog_syslog(LOG_ERR, _("Error getting random seed: %s, aborting"), - krb5_get_error_message(context, ret)); - svcauth_gssapi_unset_names(); - loop_free(ctx); - kadm5_destroy(global_server_handle); - krb5_klog_close(context); - exit(1); - } + if (ret) + fail_to_start(ret, _("getting random seed")); - if (params.iprop_enabled == TRUE) - ulog_set_role(hctx, IPROP_MASTER); - else - ulog_set_role(hctx, IPROP_NULL); + if (params.iprop_enabled == TRUE) { + ulog_set_role(context, IPROP_MASTER); - log_ctx = hctx->kdblog_context; + ret = ulog_map(context, params.iprop_logfile, params.iprop_ulogsize, + FKADMIND, db_args); + if (ret) + fail_to_start(ret, _("mapping update log")); - if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) { - /* - * IProp is enabled, so let's map in the update log - * and setup the service. - */ - if ((ret = ulog_map(hctx, params.iprop_logfile, - params.iprop_ulogsize, FKADMIND, db_args)) != 0) { - fprintf(stderr, - _("%s: %s while mapping update log (`%s.ulog')\n"), - whoami, error_message(ret), params.dbname); - krb5_klog_syslog(LOG_ERR, - _("%s while mapping update log (`%s.ulog')"), - error_message(ret), params.dbname); - loop_free(ctx); - krb5_klog_close(context); - exit(1); - } - - - if (nofork) + if (nofork) { fprintf(stderr, _("%s: create IPROP svc (PROG=%d, VERS=%d)\n"), - whoami, KRB5_IPROP_PROG, KRB5_IPROP_VERS); - -#if 0 - if (!svc_create(krb5_iprop_prog_1, - KRB5_IPROP_PROG, KRB5_IPROP_VERS, - "circuit_v")) { - fprintf(stderr, - _("%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n"), - whoami, - KRB5_IPROP_PROG, KRB5_IPROP_VERS); - krb5_klog_syslog(LOG_ERR, - _("Cannot create IProp RPC service (PROG=%d, VERS=%d), failing."), - KRB5_IPROP_PROG, KRB5_IPROP_VERS); - loop_free(ctx); - krb5_klog_close(context); - exit(1); - } -#endif - -#if 0 /* authgss only? */ - if ((ret = kiprop_get_adm_host_srv_name(context, - params.realm, - &kiprop_name)) != 0) { - krb5_klog_syslog(LOG_ERR, - _("%s while getting IProp svc name, failing"), - error_message(ret)); - fprintf(stderr, - _("%s: %s while getting IProp svc name, failing\n"), - whoami, error_message(ret)); - loop_free(ctx); - krb5_klog_close(context); - exit(1); - } - - auth_gssapi_name iprop_name; - iprop_name.name = build_princ_name(foo, bar); - if (iprop_name.name == NULL) { - foo error; + progname, KRB5_IPROP_PROG, KRB5_IPROP_VERS); } - iprop_name.type = nt_krb5_name_oid; - if (svcauth_gssapi_set_names(&iprop_name, 1) == FALSE) { - foo error; - } - if (!rpc_gss_set_svc_name(kiprop_name, "kerberos_v5", 0, - KRB5_IPROP_PROG, KRB5_IPROP_VERS)) { - rpc_gss_error_t err; - (void) rpc_gss_get_error(&err); - - krb5_klog_syslog(LOG_ERR, - _("Unable to set RPCSEC_GSS service name (`%s'), failing."), - kiprop_name ? kiprop_name : ""); - - fprintf(stderr, - _("%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n"), - whoami, - kiprop_name ? kiprop_name : ""); - - if (nofork) { - fprintf(stderr, - "%s: set svc name (rpcsec err=%d, sys err=%d)\n", - whoami, - err.rpc_gss_error, - err.system_error); - } - - loop_free(ctx); - exit(1); - } - free(kiprop_name); -#endif } krb5_klog_syslog(LOG_INFO, _("starting")); if (nofork) - fprintf(stderr, _("%s: starting...\n"), whoami); + fprintf(stderr, _("%s: starting...\n"), progname); - verto_run(ctx); + verto_run(vctx); krb5_klog_syslog(LOG_INFO, _("finished, exiting")); /* Clean up memory, etc */ svcauth_gssapi_unset_names(); kadm5_destroy(global_server_handle); - loop_free(ctx); + loop_free(vctx); kadm5int_acl_finish(context, 0); - if(gss_changepw_name) { - (void) gss_release_name(&OMret, &gss_changepw_name); - } - if(gss_oldchangepw_name) { - (void) gss_release_name(&OMret, &gss_oldchangepw_name); - } - for(i = 0 ; i < 4; i++) { - if (names[i].name) { - free(names[i].name); - } - } + (void)gss_release_name(&minor_status, &gss_changepw_name); + (void)gss_release_name(&minor_status, &gss_oldchangepw_name); + for (i = 0; i < 4; i++) + free(names[i].name); krb5_klog_close(context); krb5_free_context(context); exit(2); } - -/* - * Function: build_princ_name - * - * Purpose: takes a name and a realm and builds a string that can be - * consumed by krb5_parse_name. - * - * Arguments: - * name (input) name to be part of principal - * realm (input) realm part of principal - * char * pointing to "name@realm" - * - * Requires: - * name be non-null. - * - * Effects: - * Modifies: - */ - -char *build_princ_name(char *name, char *realm) -{ - char *fullname; - - if (realm) { - if (asprintf(&fullname, "%s@%s", name, realm) < 0) - fullname = NULL; - } else - fullname = strdup(name); - - return fullname; -} - -/* - * Function: log_badverf - * - * Purpose: Call from GSS-API Sun RPC for garbled/forged/replayed/etc - * messages. - * - * Argiments: - * client_name (r) GSS-API client name - * server_name (r) GSS-API server name - * rqst (r) RPC service request - * msg (r) RPC message - * data (r) arbitrary data (NULL), not used - * - * Effects: - * - * Logs the invalid request via krb5_klog_syslog(); see functional spec for - * format. - */ -void log_badverf(gss_name_t client_name, gss_name_t server_name, - struct svc_req *rqst, struct rpc_msg *msg, char - *data) -{ - struct procnames { - rpcproc_t proc; - const char *proc_name; - }; - static const struct procnames proc_names[] = { - {1, "CREATE_PRINCIPAL"}, - {2, "DELETE_PRINCIPAL"}, - {3, "MODIFY_PRINCIPAL"}, - {4, "RENAME_PRINCIPAL"}, - {5, "GET_PRINCIPAL"}, - {6, "CHPASS_PRINCIPAL"}, - {7, "CHRAND_PRINCIPAL"}, - {8, "CREATE_POLICY"}, - {9, "DELETE_POLICY"}, - {10, "MODIFY_POLICY"}, - {11, "GET_POLICY"}, - {12, "GET_PRIVS"}, - {13, "INIT"}, - {14, "GET_PRINCS"}, - {15, "GET_POLS"}, - {16, "SETKEY_PRINCIPAL"}, - {17, "SETV4KEY_PRINCIPAL"}, - {18, "CREATE_PRINCIPAL3"}, - {19, "CHPASS_PRINCIPAL3"}, - {20, "CHRAND_PRINCIPAL3"}, - {21, "SETKEY_PRINCIPAL3"}, - {22, "PURGEKEYS"}, - {23, "GET_STRINGS"}, - {24, "SET_STRING"} - }; -#define NPROCNAMES (sizeof (proc_names) / sizeof (struct procnames)) - OM_uint32 minor; - gss_buffer_desc client, server; - gss_OID gss_type; - const char *a; - rpcproc_t proc; - unsigned int i; - const char *procname; - size_t clen, slen; - char *cdots, *sdots; - - client.length = 0; - client.value = NULL; - server.length = 0; - server.value = NULL; - - (void) gss_display_name(&minor, client_name, &client, &gss_type); - (void) gss_display_name(&minor, server_name, &server, &gss_type); - if (client.value == NULL) { - client.value = "(null)"; - clen = sizeof("(null)") -1; - } else { - clen = client.length; - } - trunc_name(&clen, &cdots); - if (server.value == NULL) { - server.value = "(null)"; - slen = sizeof("(null)") - 1; - } else { - slen = server.length; - } - trunc_name(&slen, &sdots); - a = client_addr(rqst->rq_xprt); - - proc = msg->rm_call.cb_proc; - procname = NULL; - for (i = 0; i < NPROCNAMES; i++) { - if (proc_names[i].proc == proc) { - procname = proc_names[i].proc_name; - break; - } - } - if (procname != NULL) - krb5_klog_syslog(LOG_NOTICE, - _("WARNING! Forged/garbled request: %s, claimed " - "client = %.*s%s, server = %.*s%s, addr = %s"), - procname, (int) clen, (char *) client.value, cdots, - (int) slen, (char *) server.value, sdots, a); - else - krb5_klog_syslog(LOG_NOTICE, - _("WARNING! Forged/garbled request: %d, claimed " - "client = %.*s%s, server = %.*s%s, addr = %s"), - proc, (int) clen, (char *) client.value, cdots, - (int) slen, (char *) server.value, sdots, a); - - (void) gss_release_buffer(&minor, &client); - (void) gss_release_buffer(&minor, &server); -} - -/* - * Function: log_miscerr - * - * Purpose: Callback from GSS-API Sun RPC for miscellaneous errors - * - * Arguments: - * rqst (r) RPC service request - * msg (r) RPC message - * error (r) error message from RPC - * data (r) arbitrary data (NULL), not used - * - * Effects: - * - * Logs the error via krb5_klog_syslog(); see functional spec for - * format. - */ -void log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, - char *error, char *data) -{ - krb5_klog_syslog(LOG_NOTICE, _("Miscellaneous RPC error: %s, %s"), - client_addr(rqst->rq_xprt), error); -} - - - -/* - * Function: log_badauth - * - * Purpose: Callback from GSS-API Sun RPC for authentication - * failures/errors. - * - * Arguments: - * major (r) GSS-API major status - * minor (r) GSS-API minor status - * addr (r) originating address - * data (r) arbitrary data (NULL), not used - * - * Effects: - * - * Logs the GSS-API error via krb5_klog_syslog(); see functional spec for - * format. - */ -void log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data) -{ - /* Authentication attempt failed: , */ - - krb5_klog_syslog(LOG_NOTICE, _("Authentication attempt failed: %s, " - "GSS-API error strings are:"), - client_addr(xprt)); - log_badauth_display_status(" ", major, minor); - krb5_klog_syslog(LOG_NOTICE, _(" GSS-API error strings complete.")); -} - -void log_badauth_display_status(char *msg, OM_uint32 major, OM_uint32 minor) -{ - log_badauth_display_status_1(msg, major, GSS_C_GSS_CODE, 0); - log_badauth_display_status_1(msg, minor, GSS_C_MECH_CODE, 0); -} - -void log_badauth_display_status_1(char *m, OM_uint32 code, int type, - int rec) -{ - OM_uint32 gssstat, minor_stat; - gss_buffer_desc msg; - OM_uint32 msg_ctx; - - msg_ctx = 0; - while (1) { - gssstat = gss_display_status(&minor_stat, code, - type, GSS_C_NULL_OID, - &msg_ctx, &msg); - if (gssstat != GSS_S_COMPLETE) { - if (!rec) { - log_badauth_display_status_1(m,gssstat,GSS_C_GSS_CODE,1); - log_badauth_display_status_1(m, minor_stat, - GSS_C_MECH_CODE, 1); - } else - krb5_klog_syslog(LOG_ERR, - _("GSS-API authentication error %.*s: " - "recursive failure!"), (int) msg.length, - (char *) msg.value); - return; - } - - krb5_klog_syslog(LOG_NOTICE, "%s %.*s", m, (int)msg.length, - (char *)msg.value); - (void) gss_release_buffer(&minor_stat, &msg); - - if (!msg_ctx) - break; - } -} -- cgit