summaryrefslogtreecommitdiffstats
path: root/src/kadmin/v5passwdd/proto_serv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kadmin/v5passwdd/proto_serv.c')
-rw-r--r--src/kadmin/v5passwdd/proto_serv.c860
1 files changed, 860 insertions, 0 deletions
diff --git a/src/kadmin/v5passwdd/proto_serv.c b/src/kadmin/v5passwdd/proto_serv.c
new file mode 100644
index 000000000..d87a71a64
--- /dev/null
+++ b/src/kadmin/v5passwdd/proto_serv.c
@@ -0,0 +1,860 @@
+/*
+ * kadmin/v5server/proto_serv.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * proto_serv.c - Engage in protocol. This module reflects the connection
+ * protocol as implemented in lib/krb5/os/adm_conn.c. Any changes
+ * in one module must be reflected in the other.
+ */
+#include <signal.h>
+#define NEED_SOCKETS
+#include "k5-int.h"
+#include "com_err.h"
+#include "kadm5_defs.h"
+#include "adm.h"
+#include "adm_proto.h"
+#include <setjmp.h>
+
+static const char *proto_addrs_msg = "\004%d: cannot get memory for addresses";
+static const char *proto_rcache_msg = "\004%d: cannot get replay cache";
+static const char *proto_ap_req_msg = "\004%d: error reading AP_REQ message";
+static const char *proto_auth_con_msg = "\004%d: cannot get authorization context";
+static const char *proto_rd_req_msg = "\004%d: cannot decode AP_REQ message";
+static const char *proto_mk_rep_msg = "\004%d: cannot generate AP_REP message";
+static const char *proto_wr_rep_msg = "\004%d: cannot write AP_REP message";
+static const char *proto_conn_abort_msg = "\007%d: connection destroyed by client";
+static const char *proto_seq_err_msg = "\004%d: protocol sequence violation";
+static const char *proto_rd_cmd_msg = "\004%d: cannot read administrative protocol command";
+static const char *proto_db_open_msg = "\004%d: cannot open database";
+static const char *proto_db_close_msg = "\004%d: cannot close database";
+static const char *proto_wr_reply_msg = "\004%d: cannot write administrative protocol reply";
+static const char *proto_fmt_reply_msg = "\004%d: cannot format administrative protocol reply";
+extern char *programname;
+
+static int proto_proto_timeout = -1;
+static int proto_debug_level = 0;
+#if POSIX_SETJMP
+static sigjmp_buf timeout_jmp;
+#else /* POSIX_SETJMP */
+static jmp_buf timeout_jmp;
+#endif /* POSIX_SETJMP */
+
+static krb5_sigtype
+proto_alarmclock(signo)
+ int signo;
+{
+#if POSIX_SETJMP
+ siglongjmp(timeout_jmp, 1);
+#else /* POSIX_SETJMP */
+ longjmp(timeout_jmp, 1);
+#endif /* POSIX_SETJMP */
+ /* NOTREACHED */
+}
+
+krb5_error_code
+proto_init(kcontext, debug_level, timeo)
+ krb5_context kcontext;
+ int debug_level;
+ int timeo;
+{
+ krb5_error_code kret;
+
+ proto_debug_level = debug_level;
+ DPRINT(DEBUG_CALLS, proto_debug_level,
+ ("* proto_init(timeo=%d)\n", timeo));
+ kret = 0;
+ proto_proto_timeout = timeo;
+ DPRINT(DEBUG_CALLS, proto_debug_level, ("X proto_init() = %d\n", kret));
+ return(kret);
+}
+
+void
+proto_finish(kcontext, debug_level)
+ krb5_context kcontext;
+ int debug_level;
+{
+ DPRINT(DEBUG_CALLS, proto_debug_level, ("* proto_finish()\n"));
+ DPRINT(DEBUG_CALLS, proto_debug_level, ("X proto_finish()\n"));
+}
+
+krb5_error_code
+proto_serv(kcontext, my_id, cl_sock, sv_p, cl_p)
+ krb5_context kcontext;
+ krb5_int32 my_id;
+ int cl_sock;
+ void *sv_p;
+ void *cl_p;
+{
+ krb5_error_code kret;
+ struct sockaddr_in *cl_addr;
+ struct sockaddr_in *sv_addr;
+
+ krb5_data in_data;
+ krb5_data out_data;
+ krb5_rcache rcache;
+ krb5_auth_context auth_context;
+ krb5_flags ap_options;
+ krb5_ticket *ticket;
+ krb5_address *local;
+ krb5_address *remote;
+
+#if POSIX_SIGNALS
+ struct sigaction s_action;
+#endif /* POSIX_SIGNALS */
+
+ char *curr_lang = (char *) NULL;
+ krb5_boolean mime_setting = 0;
+
+ krb5_int32 num_args;
+ krb5_data *arglist;
+
+ krb5_boolean db_opened;
+
+ cl_addr = (struct sockaddr_in *) cl_p;
+ sv_addr = (struct sockaddr_in *) sv_p;
+ DPRINT(DEBUG_CALLS, proto_debug_level,
+ ("* proto_serv(id=%d, sock=%d, local=%x, remote=%x)\n",
+ my_id, cl_sock,
+ ntohl(sv_addr->sin_addr.s_addr),
+ ntohl(cl_addr->sin_addr.s_addr)));
+
+ /* Initialize */
+ memset((char *) &in_data, 0, sizeof(in_data));
+ memset((char *) &out_data, 0, sizeof(out_data));
+ num_args = 0;
+ local = (krb5_address *) NULL;
+ remote = (krb5_address *) NULL;
+ ticket = (krb5_ticket *) NULL;
+ rcache = (krb5_rcache) NULL;
+#if POSIX_SIGNALS
+ (void) sigemptyset(&s_action.sa_mask);
+ s_action.sa_flags = 0;
+#endif /* POSIX_SIGNALS */
+ db_opened = 0;
+
+ /* Get memory for addresses */
+ local = (krb5_address *) malloc(sizeof(krb5_address));
+ remote = (krb5_address *) malloc(sizeof(krb5_address));
+ if (!local || !remote) {
+ kret = ENOMEM;
+ com_err(programname, kret, proto_addrs_msg, my_id);
+ goto cleanup;
+ }
+
+ local->contents = (krb5_octet *) malloc(sizeof(struct in_addr));
+ remote->contents = (krb5_octet *) malloc(sizeof(struct in_addr));
+ if (!local->contents || !remote->contents) {
+ kret = ENOMEM;
+ com_err(programname, kret, proto_addrs_msg, my_id);
+ goto cleanup;
+ }
+
+ /*
+ * First setup the replay cache.
+ */
+ if (kret = krb5_get_server_rcache(kcontext,
+ krb5_princ_component(kcontext,
+ net_server_princ(),
+ 0),
+ &rcache)) {
+ com_err(programname, kret, proto_rcache_msg, my_id);
+ goto cleanup;
+ }
+
+ /* Initialize the auth context */
+ if (kret = krb5_auth_con_init(kcontext, &auth_context)) {
+ com_err(programname, kret, proto_auth_con_msg, my_id);
+ goto cleanup;
+ }
+
+ krb5_auth_con_setrcache(kcontext, auth_context, rcache);
+
+ /*
+ * Set up addresses.
+ */
+ local->addrtype = remote->addrtype = ADDRTYPE_INET;
+ local->length = remote->length = sizeof(struct in_addr);
+ memcpy((char *) local->contents,
+ (char *) &sv_addr->sin_addr,
+ sizeof(struct in_addr));
+ memcpy((char *) remote->contents,
+ (char *) &cl_addr->sin_addr,
+ sizeof(struct in_addr));
+ krb5_auth_con_setflags(kcontext, auth_context,
+ KRB5_AUTH_CONTEXT_RET_SEQUENCE|
+ KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+ krb5_auth_con_setaddrs(kcontext, auth_context, local, remote);
+
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:read message(local=%x, remote=%x)\n",
+ my_id,
+ ntohl(sv_addr->sin_addr.s_addr),
+ ntohl(cl_addr->sin_addr.s_addr)));
+ /* Now, read in the AP_REQ message and decode it. */
+ if (kret = krb5_read_message(kcontext,
+ (krb5_pointer) &cl_sock,
+ &in_data)) {
+ com_err(programname, kret, proto_ap_req_msg, my_id);
+ goto cleanup;
+ }
+
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:parse message(%d bytes)\n", my_id, in_data.length));
+
+ /* Parse the AP_REQ message */
+ if (kret = krb5_rd_req(kcontext,
+ &auth_context,
+ &in_data,
+ net_server_princ(),
+ key_keytab_id(),
+ &ap_options,
+ &ticket)) {
+ com_err(programname, kret, proto_rd_req_msg, my_id);
+ goto err_reply;
+ }
+
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:check AP_REQ(options are %x)\n", my_id, ap_options));
+ /* Check our options */
+ if ((ap_options & AP_OPTS_MUTUAL_REQUIRED) == 0) {
+ kret = KRB5KRB_AP_ERR_MSG_TYPE;
+ goto err_reply;
+ }
+
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:make AP_REP\n", my_id));
+ if (kret = krb5_mk_rep(kcontext, auth_context, &out_data)) {
+ com_err(programname, kret, proto_mk_rep_msg, my_id);
+ goto cleanup;
+ }
+
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:write AP_REP(%d bytes)\n", my_id, out_data.length));
+ if (kret = krb5_write_message(kcontext,
+ (krb5_pointer) &cl_sock,
+ &out_data)) {
+ com_err(programname, kret, proto_wr_rep_msg, my_id);
+ goto cleanup;
+ }
+
+ /*
+ * Initialization is now complete.
+ *
+ * If enabled, the protocol times out after proto_proto_timeout seconds.
+ */
+ if (
+#if POSIX_SETJMP
+ sigsetjmp(timeout_jmp, 1) == 0
+#else /* POSIX_SETJMP */
+ setjmp(timeout_jmp) == 0
+#endif /* POSIX_SETJMP */
+ ) {
+ if (proto_proto_timeout > 0) {
+#if POSIX_SIGNALS
+ s_action.sa_handler = proto_alarmclock;
+ (void) sigaction(SIGALRM, &s_action, (struct sigaction *) NULL);
+#else /* POSIX_SIGNALS */
+ signal(SIGALRM, proto_alarmclock);
+#endif /* POSIX_SIGNALS */
+ }
+ /*
+ * Loop forever - or until somebody puts us out of our misery.
+ */
+ while (1) {
+ krb5_int32 cmd_error;
+ char err_str[1024];
+ krb5_int32 cmd_repl_ncomps;
+ krb5_data *cmd_repl_complist;
+ int do_quit;
+
+ /*
+ * Read a command and figure out what to do.
+ */
+ if (proto_proto_timeout > 0)
+ alarm(proto_proto_timeout);
+ num_args = 0;
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:waiting for command\n", my_id));
+ kret = krb5_read_adm_cmd(kcontext,
+ (krb5_pointer) &cl_sock,
+ auth_context,
+ &num_args,
+ &arglist);
+ if (proto_proto_timeout > 0)
+ alarm(0);
+ if (kret) {
+ /*
+ * It's OK to have connections abort here.
+ */
+ if (kret == ECONNABORTED) {
+ com_err(programname, kret, proto_conn_abort_msg, my_id);
+ kret = 0;
+ }
+ else if (kret == KRB5KRB_AP_ERR_BADORDER) {
+ com_err(programname, kret, proto_seq_err_msg, my_id);
+ kret = 0;
+ }
+ else
+ com_err(programname, kret, proto_rd_cmd_msg, my_id);
+ goto cleanup;
+ }
+
+ cmd_error = KRB5_ADM_SUCCESS;
+ do_quit = 0;
+
+ /*
+ * First open the database. We only have it open for the
+ * lifetime of a command so that we are sure to close it after
+ * performing an update. This also reduces the likelihood
+ * that somebody'll have stale data lying around since we're
+ * most likely going to change something here.
+ */
+ if ((kret = key_open_db(kcontext))) {
+ com_err(programname, kret, proto_db_open_msg, my_id);
+ goto cleanup;
+ }
+ else
+ db_opened = 1;
+
+ /*
+ * Now check our arguments.
+ */
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:parse command\n", my_id));
+ cmd_repl_ncomps = 0;
+ cmd_repl_complist = (krb5_data *) NULL;
+ if (num_args > 0) {
+ if (!strcasecmp(arglist[0].data, KRB5_ADM_QUIT_CMD)) {
+ /*
+ * QUIT command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:QUIT command\n", my_id));
+ /* QUIT takes no arguments */
+ if (num_args == 1) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:QUIT command syntax OK\n", my_id));
+ do_quit = 1;
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:QUIT command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ strcpy(err_str,
+ "Bad argument list format for quit command.");
+ }
+ }
+ else if (!strcasecmp(arglist[0].data, KRB5_ADM_CHECKPW_CMD)) {
+ /*
+ * CHECKPW command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHECKPW command\n", my_id));
+ if (num_args == 2) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHECKPW command syntax OK\n", my_id));
+ cmd_error = 0;
+ err_str[0] = '\0';
+#if 0
+ cmd_error = pwd_check(kcontext,
+ proto_debug_level,
+ auth_context,
+ ticket,
+ &arglist[1],
+ &err_str);
+#endif
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHECKPW command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+
+ strcpy(err_str,
+ "Bad argument list format for checkpw command.");
+ }
+ }
+ else if (!strcasecmp(arglist[0].data, KRB5_ADM_CHANGEPW_CMD)) {
+ /*
+ * CHANGEPW command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGEPW command\n", my_id));
+ if (num_args == 3) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGEPW command syntax OK\n", my_id));
+ cmd_error = pwd_change(kcontext,
+ proto_debug_level,
+ auth_context,
+ ticket,
+ &arglist[1],
+ &arglist[2],
+ &err_str);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGEPW command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ strcpy(err_str,
+ "Bad argument list format for changepw command.");
+ }
+ }
+#if 0
+#ifdef MOTD_SUPPORTED
+ else if (!strcasecmp(arglist[0].data, KRB5_ADM_MOTD_CMD)) {
+ /*
+ * MOTD command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MOTD command\n", my_id));
+ if (num_args <= 2) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MOTD command syntax OK\n", my_id));
+ printf("@@@ motd command ");
+ if (num_args == 2)
+ printf("context is %s", arglist[2].data);
+ printf("\n");
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MOTD command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+#endif /* MOTD_SUPPORTED */
+#ifdef MIME_SUPPORTED
+ else if (!strcasecmp(arglist[0].data, KRB5_ADM_MIME_CMD)) {
+ /*
+ * MIME command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MIME command\n", my_id));
+ if (num_args == 1) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MIME command syntax OK\n", my_id));
+ mime_setting = 1;
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MIME command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+#endif /* MIME_SUPPORTED */
+#ifdef LANGUAGES_SUPPORTED
+ else if (!strcasecmp(arglist[0].data, KRB5_ADM_LANGUAGE_CMD)) {
+ /*
+ * LANGUAGE command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:LANGUAGE command\n", my_id));
+ if (num_args == 2) {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:LANGUAGE command syntax OK\n", my_id));
+ if (output_lang_supported(arglist[1].data)) {
+ if (curr_lang)
+ free(curr_lang);
+ curr_lang = (char *)
+ malloc(strlen(arglist[1].data));
+ if (curr_lang)
+ strcpy(curr_lang, arglist[1].data);
+ }
+ else
+ cmd_error = KRB5_ADM_LANG_NOT_SUPPORTED;
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:LANGUAGE command syntax BAD\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+#endif /* LANGUAGES_SUPPORTED */
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_ADD_PRINC_CMD)) {
+ /*
+ * ADD PRINCIPAL command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:ADD PRINCIPAL command\n", my_id));
+ /* At least one argument */
+ if (num_args > 1) {
+ cmd_error = admin_add_principal(kcontext,
+ proto_debug_level,
+ ticket,
+ num_args-1,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:ADD PRINCIPAL command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_DEL_PRINC_CMD)) {
+ /*
+ * DELETE PRINCIPAL command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:DELETE PRINCIPAL command\n", my_id));
+ /* Only one argument */
+ if (num_args == 2) {
+ cmd_error = admin_delete_principal(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:DELETE PRINCIPAL command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_REN_PRINC_CMD)) {
+ /*
+ * RENAME PRINCIPAL command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:RENAME PRINCIPAL command\n", my_id));
+ /* Two arguments */
+ if (num_args == 3) {
+ cmd_error = admin_rename_principal(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1],
+ &arglist[2]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:RENAME PRINCIPAL command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_MOD_PRINC_CMD)) {
+ /*
+ * MODIFY PRINCIPAL command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MODIFY PRINCIPAL command\n", my_id));
+ /* At least one argument */
+ if (num_args > 1) {
+ cmd_error = admin_modify_principal(kcontext,
+ proto_debug_level,
+ ticket,
+ num_args-1,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:MODIFY PRINCIPAL command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_CHG_OPW_CMD)) {
+ /*
+ * CHANGE OTHER'S PASSWORD command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGE OTHER'S PASSWORD command\n", my_id));
+ /* Two arguments */
+ if (num_args == 3) {
+ cmd_error = admin_change_opwd(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1],
+ &arglist[2]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGE OTHER'S PASSWORD command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_CHG_ORPW_CMD)) {
+ /*
+ * CHANGE OTHER'S RANDOM PASSWORD command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGE OTHER'S RANDOM PASSWORD command\n", my_id));
+ /* One argument */
+ if (num_args == 2) {
+ cmd_error = admin_change_orandpwd(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:CHANGE OTHER'S RANDOM PASSWORD command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_INQ_PRINC_CMD)) {
+ /*
+ * INQUIRE PRINCIPAL command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:INQUIRE PRINCIPAL command\n", my_id));
+ /* One argument */
+ if (num_args == 2) {
+ cmd_error = admin_inquire(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1],
+ &cmd_repl_ncomps,
+ &cmd_repl_complist);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:INQUIRE PRINCIPAL command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_EXT_KEY_CMD)) {
+ /*
+ * EXTRACT KEY command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:EXTRACT KEY command\n", my_id));
+ /* Two arguments */
+ if (num_args == 3) {
+ cmd_error = admin_extract_key(kcontext,
+ proto_debug_level,
+ ticket,
+ &arglist[1],
+ &arglist[2],
+ &cmd_repl_ncomps,
+ &cmd_repl_complist);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:EXTRACT KEY command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_ADD_KEY_CMD)) {
+ /*
+ * ADD KEY command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:ADD KEY command\n", my_id));
+ /* Must have at least three arguments */
+ if (num_args > 3) {
+ cmd_error = admin_add_key(kcontext,
+ proto_debug_level,
+ ticket,
+ num_args-1,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:ADD KEY command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+ else if (!strcasecmp(arglist[0].data,
+ KRB5_ADM_DEL_KEY_CMD)) {
+ /*
+ * DELETE KEY command handling here.
+ */
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:DELETE KEY command\n", my_id));
+ /* At least three arguments */
+ if (num_args > 3) {
+ cmd_error = admin_delete_key(kcontext,
+ proto_debug_level,
+ ticket,
+ num_args-1,
+ &arglist[1]);
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:DELETE KEY command syntax BAD\n",
+ my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ err_aux = KADM_BAD_ARGS;
+ }
+ }
+#endif /* 0 */
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:UNKNOWN command %s\n", my_id,
+ arglist[0].data));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ sprintf(err_str, "Command %s not supported.", arglist[0]);
+ }
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level,
+ ("> %d:NO command!\n", my_id));
+ cmd_error = KRB5_ADM_CMD_UNKNOWN;
+ strcpy(err_str, "No command in message.");
+ }
+
+ /*
+ * Close the database.
+ */
+ if ((kret = key_close_db(kcontext))) {
+ com_err(programname, kret, proto_db_close_msg, my_id);
+ goto cleanup;
+ }
+ else
+ db_opened = 0;
+
+ /*
+ * Now make the reply.
+ */
+ DPRINT(DEBUG_PROTO, proto_debug_level,
+ ("= %d:sending reply(stat=%d)\n", my_id, cmd_error));
+ if (cmd_error == KRB5_ADM_SUCCESS) {
+ kret = krb5_send_adm_reply(kcontext,
+ (krb5_pointer) &cl_sock,
+ auth_context,
+ cmd_error,
+ cmd_repl_ncomps,
+ cmd_repl_complist);
+ if (kret) {
+ com_err(programname, kret, proto_wr_reply_msg, my_id);
+ goto cleanup;
+ }
+ }
+ else {
+ char *adm_errmsg;
+ krb5_data reply_comps;
+
+ reply_comps.data = err_str;
+ reply_comps.length = strlen(err_str);
+ kret = krb5_send_adm_reply(kcontext,
+ (krb5_pointer) &cl_sock,
+ auth_context,
+ cmd_error,
+ 1,
+ &reply_comps);
+ if (kret) {
+ com_err(programname, kret, proto_wr_reply_msg, my_id);
+ goto cleanup;
+ }
+ }
+ if (cmd_repl_ncomps > 0)
+ krb5_free_adm_data(kcontext,
+ cmd_repl_ncomps,
+ cmd_repl_complist);
+
+ if (do_quit)
+ break;
+ krb5_free_adm_data(kcontext, num_args, arglist);
+ }
+ }
+ else {
+ DPRINT(DEBUG_REQUESTS, proto_debug_level, ("connection timed out"));
+ }
+
+
+ err_reply:
+ if (kret) {
+ krb5_error_code er_kret;
+ krb5_error errbuf;
+ char *errmsg;
+ krb5_data errout;
+
+ memset((char *) &errbuf, 0, sizeof(errbuf));
+ krb5_us_timeofday(kcontext, &errbuf.stime, &errbuf.susec);
+ errbuf.server = net_server_princ();
+ errbuf.error = kret - ERROR_TABLE_BASE_krb5;
+ if (errbuf.error > 127)
+ errbuf.error = KRB5KRB_ERR_GENERIC;
+ /* Format the error message in our language */
+ errmsg = error_message(kret);
+ errbuf.text.length = strlen(errmsg);
+ errbuf.text.data = errmsg;
+ er_kret = krb5_mk_error(kcontext, &errbuf, &errout);
+ if (!er_kret)
+ krb5_write_message(kcontext, (krb5_pointer) &cl_sock, &errout);
+ free(errbuf.text.data);
+ krb5_xfree(errout.data);
+ }
+
+ cleanup:
+ /* If the alarm was set, make sure it's cancelled */
+ if (proto_proto_timeout > 0)
+ alarm(0);
+ if (ticket)
+ krb5_free_ticket(kcontext, ticket);
+ /*
+ * Don't need to close the replay cache because it's attached to the
+ * auth context.
+ */
+ if (auth_context)
+ krb5_auth_con_free(kcontext, auth_context);
+ if (curr_lang)
+ free(curr_lang);
+ if (num_args)
+ krb5_free_adm_data(kcontext, num_args, arglist);
+ if (in_data.data)
+ krb5_xfree(in_data.data);
+ if (out_data.data)
+ krb5_xfree(out_data.data);
+ if (local && local->contents)
+ free(local->contents);
+ if (remote && remote->contents)
+ free(remote->contents);
+ if (local)
+ free(local);
+ if (remote)
+ free(remote);
+ if (db_opened)
+ key_close_db(kcontext);
+ close(cl_sock);
+
+ done:
+ DPRINT(DEBUG_CALLS, proto_debug_level, ("X proto_serv() = %d\n", kret));
+ return(kret);
+}