#include <com_err.h>
#include <krb.h>
+#include <krb5.h>
#include <sys/types.h>
RCSID("$Header$");
extern char *whoami;
+extern krb5_context context;
int mrcl_connect(char *server, char *client, int version, int auth)
{
if (auth)
{
- status = mr_auth(client);
+ status = mr_krb5_auth(client);
if (status)
{
com_err(whoami, status, "while authenticating to Moira.");
char *mrcl_krb_user(void)
{
- int status;
- static char pname[ANAME_SZ];
+ int flags = 0;
+ krb5_ccache cache = NULL;
+ krb5_principal princ;
+ krb5_error_code status;
+ char *name;
+
+ if (!context)
+ krb5_init_context(&context);
- status = tf_init(TKT_FILE, R_TKT_FIL);
- if (status == KSUCCESS)
+ status = krb5_cc_default(context, &cache);
+ if (status)
{
- status = tf_get_pname(pname);
- tf_close();
+ com_err(whoami, status, "while reading Kerberos ticket file.");
+ return NULL;
}
- if (status != KSUCCESS)
+ status = krb5_cc_get_principal(context, cache, &princ);
+ if (status)
{
- /* In case mr_init hasn't been called yet. */
- initialize_krb_error_table();
- status += ERROR_TABLE_BASE_krb;
- com_err(whoami, status, "reading Kerberos ticket file.");
+ com_err(whoami, status, "while retrieving principal name.");
return NULL;
}
- return pname;
+ return (char *)krb5_princ_component(context, princ, 0);
+
}
char *partial_canonicalize_hostname(char *s)
!= MRCL_SUCCESS)
exit(1);
- if ((status = mr_auth(program_name)))
+ if ((status = mr_krb5_auth(program_name)))
{
if (status == MR_USER_AUTH)
{
!= MRCL_SUCCESS)
exit(1);
- if ((status = mr_auth(program_name)))
+ if ((status = mr_krb5_auth(program_name)))
{
if (status == MR_USER_AUTH)
{
moira_server);
return MR_ABORTED;
}
- status = mr_auth(whoami);
+ status = mr_krb5_auth(whoami);
if (status)
{
com_err(whoami, status, " while re-authenticating to server %s",
if (mrcl_connect(server, NULL, 2, 0) != MRCL_SUCCESS)
exit(2);
- status = mr_auth("mrcheck");
+ status = mr_krb5_auth("mrcheck");
if (status && auth_required)
{
sprintf(buf, "\nAuthorization failure -- run \"kinit\" and try again");
void test_script(int argc, char **argv);
void test_list_requests(void);
void test_version(int argc, char **argv);
+void test_krb5_auth(void);
void set_signal_handler(int, void (*handler)(int));
void set_signal_blocking(int, int);
else if (!strcmp(argv[0], "query") || !strcmp(argv[0], "qy"))
test_query(argc, argv);
else if (!strcmp(argv[0], "auth") || !strcmp(argv[0], "a"))
- test_auth();
+ test_krb5_auth();
else if (!strcmp(argv[0], "proxy") || !strcmp(argv[0], "p"))
test_proxy(argc, argv);
else if (!strcmp(argv[0], "access"))
quit = 1;
else if (!strcmp(argv[0], "version") || !strcmp(argv[0], "v"))
test_version(argc, argv);
+ else if (!strcmp(argv[0], "krb4_auth") || !strcmp(argv[0], "4"))
+ test_auth();
else
{
fprintf(stderr, "moira: Unknown request \"%s\". "
com_err("moira (auth)", status, "");
}
+void test_krb5_auth(void)
+{
+ int status;
+
+ status = mr_krb5_auth("mrtest");
+ if (status)
+ com_err("moira (krb5_auth)", status, "");
+}
+
void test_proxy(int argc, char *argv[])
{
int status;
return MR_CANT_CONNECT;
}
- code = mr_send_auth(conn, host);
+ code = mr_send_krb5_auth(conn, host);
+ if (code)
+ code = mr_send_auth(conn, host);
if (code)
{
com_err(whoami, code, "authenticating to %s", host);
#define MR_MOTD 6
#define MR_PROXY 7
#define MR_SETVERSION 8
-#define MR_MAX_PROC 8
+#define MR_KRB5_AUTH 9
+#define MR_MAX_PROC 9
/* values used in NFS physical flags */
#define MR_FS_STUDENT 0x0001
uname(&uts);
code = mr_connect(uts.nodename);
if (!code)
- code = mr_auth("afs.incr");
+ code = mr_krb5_auth("afs.incr");
return code;
}
return 0;
#endif /*WIN32*/
/*det
if (!rc)
- rc = mr_auth("winad.incr");
+ rc = mr_krb5_auth("winad.incr");
*/
return rc;
}
if (auth)
{
- status = mr_auth(client);
+ status = mr_krb5_auth(client);
if (status)
{
com_err(whoami, status, "while authenticating to Moira.");
#include <string.h>
#include <krb.h>
+#include <krb5.h>
+
+krb5_context context = NULL;
+krb5_auth_context auth_con = NULL;
RCSID("$Header$");
return status;
}
+
+int mr_krb5_auth(char *prog)
+{
+ mr_params params, reply;
+ char host[BUFSIZ], *p;
+ char *args[2];
+ int argl[2];
+ krb5_ccache ccache = NULL;
+ krb5_data auth;
+ krb5_error_code problem = 0;
+
+ CHECK_CONNECTED;
+
+ memset(&auth, 0, sizeof(auth));
+
+ if ((problem = mr_host(host, sizeof(host) - 1)))
+ return problem;
+
+ for (p = host; *p && *p != '.'; p++)
+ {
+ if (isupper(*p))
+ *p = tolower(*p);
+ }
+ *p = '\0';
+
+ if (!context)
+ {
+ problem = krb5_init_context(&context);
+ if (problem)
+ goto out;
+ }
+
+ problem = krb5_auth_con_init(context, &auth_con);
+ if (problem)
+ goto out;
+
+ problem = krb5_cc_default(context, &ccache);
+ if (problem)
+ goto out;
+
+ problem = krb5_mk_req(context, &auth_con, NULL, MOIRA_SNAME, host, NULL,
+ ccache, &auth);
+ if (problem)
+ goto out;
+
+ params.u.mr_procno = MR_KRB5_AUTH;
+ params.mr_argc = 2;
+ params.mr_argv = args;
+ params.mr_argl = argl;
+ params.mr_argv[0] = (char *)auth.data;
+ params.mr_argl[0] = auth.length;
+ params.mr_argv[1] = prog;
+ params.mr_argl[1] = strlen(prog) + 1;
+
+ if ((problem = mr_do_call(¶ms, &reply)) == MR_SUCCESS)
+ problem = reply.u.mr_status;
+
+ mr_destroy_reply(reply);
+
+ out:
+ if (ccache)
+ krb5_cc_close(context, ccache);
+ krb5_free_data_contents(context, &auth);
+ if (auth_con)
+ krb5_auth_con_free(context, auth_con);
+ auth_con = NULL;
+
+ return problem;
+}
+
if (status)
status += ERROR_TABLE_BASE_krb;
else
- status = mr_auth("reg_svr");
+ status = mr_krb5_auth("reg_svr");
if (status)
{
com_err(whoami, status, "authenticating to moira");
#include <unistd.h>
#include <krb.h>
+#include <krb5.h>
RCSID("$Header$");
char *host;
char krb_realm[REALM_SZ];
+krb5_context context = NULL;
/* Client array and associated data. This needs to be global for _list_users */
client **clients;
krb_get_lrealm(krb_realm, 1);
+ status = krb5_init_context(&context);
+ if (status)
+ {
+ com_err(whoami, status, "Initializing krb5 context.");
+ exit(1);
+ }
+
/*
* Database initialization. Only init if database should be open.
*/
extern char *whoami, *host;
extern int proxy_acl;
+extern krb5_context context;
static int set_client(client *cl, char *kname,
char *name, char *inst, char *realm);
strncpy(cl->clname, kname, sizeof(cl->clname));
cl->clname[sizeof(cl->clname) - 1] = '\0';
- if (inst[0] == 0 && !strcmp(realm, krb_realm))
+ if ((!inst || inst[0] == 0) && !strcmp(realm, krb_realm))
ok = 1;
else
ok = 0;
/* this is in a separate function because it accesses the database */
return set_krb_mapping(cl->clname, name, ok, &cl->client_id, &cl->users_id);
}
+
+void do_krb5_auth(client *cl)
+{
+ krb5_data auth;
+ krb5_auth_context auth_con = NULL;
+ krb5_principal server = NULL, client = NULL;
+ krb5_ticket *ticket;
+ char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+ int status;
+
+ ticket = NULL;
+
+ status = krb5_auth_con_init(context, &auth_con);
+ if (status)
+ {
+ client_reply(cl, status);
+ com_err(whoami, status, "(krb5 auth context init failed)");
+ goto out;
+ }
+
+ status = krb5_sname_to_principal(context, host, MOIRA_SNAME,
+ KRB5_NT_SRV_HST, &server);
+ if (status)
+ {
+ client_reply(cl, status);
+ com_err(whoami, status, "(krb5_sname_to_principal failed)");
+ goto out;
+ }
+
+ auth.length = cl->req.mr_argl[0];
+ auth.data = cl->req.mr_argv[0];
+
+ status = krb5_rd_req(context, &auth_con, &auth, server, NULL, NULL,
+ &ticket);
+ if (status)
+ {
+ client_reply(cl, status);
+ com_err(whoami, status, " (krb5 authentication failed)");
+ goto out;
+ }
+
+ status = krb5_copy_principal(context, ticket->enc_part2->client, &client);
+ if (status)
+ {
+ client_reply(cl, status);
+ com_err(whoami, status, " (krb5_copy_principal failed)");
+ goto out;
+ }
+
+ /* Always convert to krb4 style principal name for now. */
+ status = krb5_524_conv_principal(context, client, name, inst, realm);
+ if (status)
+ {
+ client_reply(cl, status);
+ com_err(whoami, status, " (krb5_524_conv_principal failed)");
+ goto out;
+ }
+ status = set_client(cl, mr_kname_unparse(name, inst, realm), name, inst,
+ realm);
+
+ strncpy(cl->entity, cl->req.mr_argv[1], sizeof(cl->entity) - 1);
+ cl->entity[sizeof(cl->entity) - 1] = 0;
+
+ memset(&ticket, 0, sizeof(ticket)); /* Clean up session key, etc. */
+
+ com_err(whoami, 0, "krb5 auth to %s using %s, uid %d cid %d",
+ cl->clname, cl->entity, cl->users_id, cl->client_id);
+
+ if (status != MR_SUCCESS || cl->users_id != 0)
+ client_reply(cl, status);
+ else
+ client_reply(cl, MR_USER_AUTH);
+
+ out:
+ if (client)
+ krb5_free_principal(context, client);
+ if (server)
+ krb5_free_principal(context, server);
+ if (ticket)
+ krb5_free_ticket(context, ticket);
+ if (auth_con)
+ krb5_auth_con_free(context, auth_con);
+ return;
+}
"motd",
"proxy",
"version",
+ "auth_krb5",
};
int newqueries;
case MR_SETVERSION:
do_version(cl);
break;
+
+ case MR_KRB5_AUTH:
+ do_krb5_auth(cl);
+ break;
+
}
out:
#include <stdarg.h>
#include <krb.h>
+#include <krb5.h>
enum clstate { CL_ACCEPTING, CL_ACTIVE, CL_CLOSING };
/* prototypes from mr_sauth.c */
void do_auth(client *cl);
void do_proxy(client *cl);
+void do_krb5_auth(client *cl);
/* prototypes from mr_scall.c */
void do_client(client *cl);
bindir=@bindir@
sbindir=@sbindir@
-SOBJS= auth_002.o checksum.o config.o exec_002.o get_file.o \
+SOBJS= auth_002.o auth_003.o checksum.o config.o exec_002.o get_file.o \
update_server.o xfer_002.o xfer_003.o sendrecv.o
COBJS= update_test.o checksum.o client.o send_file.o ticket.o sendrecv.o
--- /dev/null
+/* $Id$
+ *
+ * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#include <mit-copyright.h>
+#include <moira.h>
+#include "update_server.h"
+
+#include <sys/utsname.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <krb.h>
+#include <krb5.h>
+
+RCSID("$Header$");
+
+static char service[] = "host";
+static char master[] = "sms";
+static char qmark[] = "???";
+
+/*
+ * authentication request auth_003:
+ *
+ * >>> (STRING) "auth_003"
+ * <<< (int) 0
+ * >>> (STRING) ticket
+ * <<< (int) code
+ *
+ */
+
+void auth_003(int conn, char *str)
+{
+ krb5_context context = NULL;
+ krb5_auth_context auth_con = NULL;
+ krb5_data auth;
+ krb5_principal server = NULL, client = NULL;
+ krb5_ticket *ticket;
+ char *p, *first, *data;
+ char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+ char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ];
+ size_t size;
+ long code;
+ struct utsname uts;
+
+ ticket = NULL;
+
+ send_ok(conn);
+
+ recv_string(conn, &data, &size);
+ auth.data = malloc(size);
+ if (!auth.data)
+ goto out;
+ memcpy(auth.data, data, size);
+ free(data);
+ auth.length = size;
+
+ code = krb5_init_context(&context);
+ if (code)
+ {
+ com_err(whoami, code, "Initializing context");
+ send_int(conn, code);
+ goto out;
+ }
+
+ code = krb5_auth_con_init(context, &auth_con);
+ if (code)
+ {
+ com_err(whoami, code, "Initializing auth context");
+ send_int(conn, code);
+ goto out;
+ }
+
+ if (uname(&uts) < 0)
+ {
+ com_err(whoami, errno, "Unable to get local hostname");
+ send_int(conn, errno);
+ goto out;
+ }
+
+ code = krb5_sname_to_principal(context, uts.nodename, service,
+ KRB5_NT_SRV_HST, &server);
+
+ if (code)
+ {
+ com_err(whoami, code, "(krb5_sname_to_principal failed)");
+ send_int(conn, code);
+ goto out;
+ }
+
+ code = krb5_rd_req(context, &auth_con, &auth, server, NULL, NULL, &ticket);
+
+ if (code)
+ {
+ strcpy(name, qmark);
+ strcpy(inst, qmark);
+ strcpy(realm, qmark);
+ com_err(whoami, code, "auth for %s.%s@%s failed", name, inst, realm);
+ send_int(conn, code);
+ goto out;
+ }
+
+ code = krb5_copy_principal(context, ticket->enc_part2->client, &client);
+ if (code)
+ {
+ com_err(whoami, code, "(krb5_copy_principal failed)");
+ send_int(conn, code);
+ goto out;
+ }
+
+ code = krb5_524_conv_principal(context, client, name, inst, realm);
+ if (code)
+ {
+ com_err(whoami, code, "(krb5_524_conv_principal_failed)");
+ send_int(conn, code);
+ goto out;
+ }
+
+ /* If there is an auth record in the config file matching the
+ * authenticator we received, then accept it. If there's no
+ * auth record, assume [master]@[local realm].
+ */
+ if ((first = p = config_lookup("auth")))
+ {
+ do
+ {
+ kname_parse(aname, ainst, arealm, p);
+ if (strcmp(aname, name) ||
+ strcmp(ainst, inst) ||
+ strcmp(arealm, realm))
+ p = config_lookup("auth");
+ else
+ p = first;
+ }
+ while (p != first);
+ }
+ else
+ {
+ strcpy(aname, master);
+ strcpy(ainst, "");
+ if (krb_get_lrealm(arealm, 1))
+ strcpy(arealm, KRB_REALM);
+ }
+ code = EPERM;
+ if (strcmp(aname, name) ||
+ strcmp(ainst, inst) ||
+ strcmp(arealm, realm))
+ {
+ com_err(whoami, code, "auth for %s.%s@%s failed", name, inst, realm);
+ send_int(conn, code);
+ goto out;
+ }
+ send_ok(conn);
+ have_authorization = 1;
+
+ out:
+ if (client)
+ krb5_free_principal(context, client);
+ if (server)
+ krb5_free_principal(context, server);
+ if (ticket)
+ krb5_free_ticket(context, ticket);
+ krb5_free_data_contents(context, &auth);
+ if (auth_con)
+ krb5_auth_con_free(context, auth_con);
+ return;
+}
#include <des.h>
#include <krb.h>
+#include <krb5.h>
RCSID("$Header$");
extern des_cblock session;
extern char *whoami;
+extern krb5_context context;
+
+int mr_send_krb5_auth(int conn, char *host_name)
+{
+ krb5_data auth;
+ int code;
+ long response;
+
+ memset(&auth, 0, sizeof(auth));
+
+ code = get_mr_krb5_update_ticket(host_name, &auth);
+ if (code)
+ goto out;
+ code = send_string(conn, "AUTH_003", 9);
+ if (code)
+ goto out;
+ code = recv_int(conn, &response);
+ if (code)
+ goto out;
+ if (response)
+ {
+ /* Talking to a server that doesn't do AUTH_003 */
+ krb5_free_data_contents(context, &auth);
+ return response;
+ }
+ code = send_string(conn, (char *)auth.data, auth.length);
+ if (code)
+ goto out;
+ code = recv_int(conn, &response);
+ if (code)
+ goto out;
+ if (response)
+ {
+ krb5_free_data_contents(context, &auth);
+ return response;
+ }
+
+ return MR_SUCCESS;
+
+ out:
+ krb5_free_data_contents(context, &auth);
+ return code;
+}
int mr_send_auth(int conn, char *host_name)
{
#include <string.h>
#include <krb.h>
+#include <krb5.h>
#include <update.h>
RCSID("$Header$");
static char master[INST_SZ] = "sms";
static char service[ANAME_SZ] = "rcmd";
des_cblock session;
+krb5_context context = NULL;
static int get_mr_tgt(void);
+int get_mr_krb5_update_ticket(char *host, krb5_data auth)
+{
+ krb5_auth_context auth_con = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_error_code code;
+
+ code = krb5_init_context(&context);
+ if (code)
+ goto out;
+
+ code = krb5_auth_con_init(context, &auth_con);
+ if (code)
+ goto out;
+
+ code = krb5_cc_default(context, &ccache);
+ if (code)
+ goto out;
+
+ code = krb5_mk_req(context, &auth_con, NULL, "host", host, NULL, ccache,
+ &auth);
+
+ out:
+ if (ccache)
+ krb5_cc_close(context, ccache);
+ if (auth_con)
+ krb5_auth_con_free(context, auth_con);
+ return code;
+}
+
int get_mr_update_ticket(char *host, KTEXT ticket)
{
int code, pass;
void (*proc)(int, char *);
} dispatch_table[] = {
{ "AUTH_002", auth_002 },
+ { "AUTH_003", auth_003 },
{ "XFER_002", xfer_002 },
{ "XFER_003", xfer_003 },
{ "EXEC_002", exec_002 },
/* prototypes for the update_server */
void auth_002(int conn, char *str);
+void auth_003(int conn, char *str);
void exec_002(int conn, char *str);
void xfer_002(int conn, char *str);
void xfer_003(int conn, char *str);
exit(1);
}
- code = mr_send_auth(conn, host);
+ code = mr_send_krb5_auth(conn, host);
+ if (code)
+ code = mr_send_auth(conn, host);
if (code)
com_err(whoami, code, "attempting authorization");
JNIEXPORT void JNICALL Java_mit_moira_MoiraConnectInternal_auth(JNIEnv *env,
jclass Class) {
int status;
- status = mr_auth("JavaInterface");
+ status = mr_krb5_auth("JavaInterface");
if (status != MR_SUCCESS) throwMoiraException(env, status);
return;
}